* [PATCH net-next] net: cavium: use module_pci_driver to simplify the code
From: Wei Yongjun @ 2018-03-28 12:51 UTC (permalink / raw)
To: Radoslaw Biernacki, Aleksey Makarov, Philippe Ombredanne,
Jan Glauber
Cc: Wei Yongjun, netdev, kernel-janitors
Use the module_pci_driver() macro to make the code simpler
by eliminating module_init and module_exit calls.
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/net/ethernet/cavium/common/cavium_ptp.c | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/cavium/common/cavium_ptp.c b/drivers/net/ethernet/cavium/common/cavium_ptp.c
index d59497a..6aeb104 100644
--- a/drivers/net/ethernet/cavium/common/cavium_ptp.c
+++ b/drivers/net/ethernet/cavium/common/cavium_ptp.c
@@ -336,18 +336,7 @@ static void cavium_ptp_remove(struct pci_dev *pdev)
.remove = cavium_ptp_remove,
};
-static int __init cavium_ptp_init_module(void)
-{
- return pci_register_driver(&cavium_ptp_driver);
-}
-
-static void __exit cavium_ptp_cleanup_module(void)
-{
- pci_unregister_driver(&cavium_ptp_driver);
-}
-
-module_init(cavium_ptp_init_module);
-module_exit(cavium_ptp_cleanup_module);
+module_pci_driver(cavium_ptp_driver);
MODULE_DESCRIPTION(DRV_NAME);
MODULE_AUTHOR("Cavium Networks <support@cavium.com>");
^ permalink raw reply related
* Re: [PATCH v3 net 1/5] tcp: feed correct number of pkts acked to cc modules also in recovery
From: Ilpo Järvinen @ 2018-03-28 12:45 UTC (permalink / raw)
To: Yuchung Cheng; +Cc: netdev, Neal Cardwell, Eric Dumazet, Sergei Shtylyov
In-Reply-To: <CAK6E8=e7=h0Z7PV9CpyurhiW-jccF+aUDfD1eSXYTWkLwUKT=A@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 8746 bytes --]
On Tue, 27 Mar 2018, Yuchung Cheng wrote:
> On Tue, Mar 27, 2018 at 7:23 AM, Ilpo Järvinen
> <ilpo.jarvinen@helsinki.fi> wrote:
> > On Mon, 26 Mar 2018, Yuchung Cheng wrote:
> >
> >> On Tue, Mar 13, 2018 at 3:25 AM, Ilpo Järvinen
> >> <ilpo.jarvinen@helsinki.fi> wrote:
> >> >
> >> > A miscalculation for the number of acknowledged packets occurs during
> >> > RTO recovery whenever SACK is not enabled and a cumulative ACK covers
> >> > any non-retransmitted skbs. The reason is that pkts_acked value
> >> > calculated in tcp_clean_rtx_queue is not correct for slow start after
> >> > RTO as it may include segments that were not lost and therefore did
> >> > not need retransmissions in the slow start following the RTO. Then
> >> > tcp_slow_start will add the excess into cwnd bloating it and
> >> > triggering a burst.
> >> >
> >> > Instead, we want to pass only the number of retransmitted segments
> >> > that were covered by the cumulative ACK (and potentially newly sent
> >> > data segments too if the cumulative ACK covers that far).
> >> >
> >> > Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
> >> > ---
> >>
> >> My understanding is there are two problems
> >>
> >> 1) your fix: the reordering logic in tcp-remove_reno_sacks requires
> >> precise cumulatively acked count, not newly acked count?
> >
> > While I'm not entirely sure if you intented to say that my fix is broken
> > or not, I thought this very difference alot while making the fix and I
> > believe that this fix is needed because of the discontinuity at RTO
> > (sacked_out is cleared as we set L-bits + lost_out). This is an artifact
> > in the imitation of sacked_out for non-SACK but at RTO we can't keep that
> > in sync because we set L-bits (and have no S-bits to guide us). Thus, we
> > cannot anymore "use" those skbs with only L-bit for the reno_sacks logic.
> >
> > In tcp_remove_reno_sacks acked - sacked_out is being used to calculate
> > tp->delivered, using plain cumulative acked causes congestion control
> > breakage later as call to tcp_cong_control will directly use the
> > difference in tp->delivered.
> >
> > This boils down the exact definition of tp->delivered (the one given in
> > the header is not detailed enough). I guess you might have better idea
> > what it exactly is since one of you has added it? There are subtle things
> > in the defination that can make it entirely unsuitable for cc decisions.
> > Should those segments that we (possibly) already counted into
> > tp->delivered during (potentially preceeding) CA_Recovery be added to it
> > for _second time_ or not? This fix avoids such double counting (the
> Where is the double counting, assuming normal DUPACK behavior?
>
> In the non-sack case:
>
> 1. upon receiving a DUPACK, we assume one packet has been delivered by
> incrementing tp->delivered in tcp_add_reno_sack()
1b. RTO here. We clear tp->sacked_out at RTO (i.e., the discontinuity
I've tried to point out quite many times already)...
> 2. upon receiving a partial ACK or an ACK that acks recovery point
> (high_seq), tp->delivered is incremented by (cumulatively acked -
> #dupacks) in tcp_remove_reno_sacks()
...and this won't happen correctly anymore after RTO (since non-SACK
won't keep #dupacks due to the discontinuity). Thus we end up adding
cumulatively acked - 0 to tp->delivered on those ACKs.
> therefore tp->delivered is tracking the # of packets delivered
> (sacked, acked, DUPACK'd) with the most information it could have
> inferred.
Since you didn't answer any of my questions about tp->delivered directly,
let me rephrase them to this example (non-SACK, of course):
4 segments outstanding. RTO recovery underway (lost_out=4, sacked_out=0).
Cwnd = 2 so the sender rexmits 2 out of 4. We get cumulative ACK for
three segments. How much should tp->delivered be incremented? 2 or 3?
...I think 2 is the right answer.
> From congestion control's perspective, it cares about the delivery
> information (e.g. how much), not the sequences (what or how).
I guess you must have missed my point. I'm talking about "how much"
whole the time. It's just about when can we account for it (and when not).
> I am pointing out that
>
> 1) your fix may fix one corner CC packet accounting issue in the
> non-SACK and CA_Loss
> 2) but it does not fix the other (major) CC packet accounting issue in
> the SACK case
You say major but it's major if and only if one is using one of the
affected cc modules which were not that many and IMHO not very mainstream
anyway (check my list from the previous email, not that I'd mind if they'd
get fixed too). The rest of the cc modules do not seem to use the incorrect
value even if some of them have the pkts_acked callback.
Other CC packet accounting (regardless of SACK) is based on tp->delivered
and tp->delivered is NOT similarly miscounted with SACK because the logic
depend on !TCPCB_SACKED_ACKED (that fails only if we have very high ACK
loss).
> 3) it breaks the dynamic dupthresh / reordering in the non-SACK case
> as tcp_check_reno_reordering requires strictly cum. ack.
I think that the current non-SACK reordering detection logic is not that
sound after RTO (but I'm yet to prove this). ...There seems to be some
failure modes which is why I even thought of disabling the whole thing
for non-SACK RTO recoveries and as it now seems you do care more about
non-SACK than you initial claimed, I might even have motivation to fix
more those corners rather than the worst bugs only ;-). ...But I'll make
the tp->delivered fix only in this patch to avoid any change this part of
the code.
> Therefore I prefer
> a) using tp->delivered to fix (1)(2)
> b) perhaps improving tp->delivered SACK emulation code in the non-SACK case
Somehow I get an impression that you might assume/say here that
tp->delivered is all correct for non-SACK? ...It isn't without a fix.
Therefore a) won't help any for non-SACK. Tp->delivered for non-SACK is
currently (mis!)calculated in tcp_remove_reno_sacks because the incorrect
pkts_acked is fed to it. ...Thus, b) is an intermediate step in the
miscalculation chain I'm fixing with this change. B) resolves also (1)
without additional changes to logic!
I've included below the updated change that only fixes tp->delivered
calculation (not tested besides compiling). ...But I think it's worse than
my previous version because tcp_remove_reno_sacks then assumes
non-sensical L|S skbs (but there seem to be other, worse limitations in
sacked_out imitation after RTO because we've all skbs marked with L-bit so
it's not that big deal for me as most of the that imitation code is no-op
anyway after RTO).
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 9a1b3c1..e11748d 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1868,7 +1868,6 @@ static void tcp_remove_reno_sacks(struct sock *sk, int acked)
if (acked > 0) {
/* One ACK acked hole. The rest eat duplicate ACKs. */
- tp->delivered += max_t(int, acked - tp->sacked_out, 1);
if (acked - 1 >= tp->sacked_out)
tp->sacked_out = 0;
else
@@ -1878,6 +1877,12 @@ static void tcp_remove_reno_sacks(struct sock *sk, int acked)
tcp_verify_left_out(tp);
}
+static void tcp_update_reno_delivered(struct tcp_sock *tp, int acked)
+{
+ if (acked > 0)
+ tp->delivered += max_t(int, acked - tp->sacked_out, 1);
+}
+
static inline void tcp_reset_reno_sack(struct tcp_sock *tp)
{
tp->sacked_out = 0;
@@ -3027,6 +3032,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, u32 prior_fack,
long seq_rtt_us = -1L;
long ca_rtt_us = -1L;
u32 pkts_acked = 0;
+ u32 rexmit_acked = 0;
+ u32 newdata_acked = 0;
u32 last_in_flight = 0;
bool rtt_update;
int flag = 0;
@@ -3056,8 +3063,10 @@ static int tcp_clean_rtx_queue(struct sock *sk, u32 prior_fack,
}
if (unlikely(sacked & TCPCB_RETRANS)) {
- if (sacked & TCPCB_SACKED_RETRANS)
+ if (sacked & TCPCB_SACKED_RETRANS) {
tp->retrans_out -= acked_pcount;
+ rexmit_acked += acked_pcount;
+ }
flag |= FLAG_RETRANS_DATA_ACKED;
} else if (!(sacked & TCPCB_SACKED_ACKED)) {
last_ackt = skb->skb_mstamp;
@@ -3070,6 +3079,8 @@ static int tcp_clean_rtx_queue(struct sock *sk, u32 prior_fack,
reord = start_seq;
if (!after(scb->end_seq, tp->high_seq))
flag |= FLAG_ORIG_SACK_ACKED;
+ else
+ newdata_acked += acked_pcount;
}
if (sacked & TCPCB_SACKED_ACKED) {
@@ -3151,6 +3162,9 @@ static int tcp_clean_rtx_queue(struct sock *sk, u32 prior_fack,
}
if (tcp_is_reno(tp)) {
+ tcp_update_reno_delivered(tp, icsk->icsk_ca_state != TCP_CA_Loss ?
+ pkts_acked :
+ rexmit_acked + newdata_acked);
tcp_remove_reno_sacks(sk, pkts_acked);
} else {
int delta;
^ permalink raw reply related
* [PATCH net-next] cxgb4: fix error return code in adap_init0()
From: Wei Yongjun @ 2018-03-28 12:51 UTC (permalink / raw)
To: Ganesh Goudar, Kumar Sanghvi; +Cc: Wei Yongjun, netdev, kernel-janitors
Fix to return a negative error code from the hash filter init error
handling case instead of 0, as done elsewhere in this function.
Fixes: 5c31254e35a8 ("cxgb4: initialize hash-filter configuration")
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 57d38f8..0072580 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -4449,7 +4449,8 @@ static int adap_init0(struct adapter *adap)
adap->params.ofldq_wr_cred = val[5];
if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_HASHFILTER)) {
- if (init_hash_filter(adap) < 0)
+ ret = init_hash_filter(adap);
+ if (ret < 0)
goto bye;
} else {
adap->params.offload = 1;
^ permalink raw reply related
* [PATCH net-next] net: bcmgenet: return NULL instead of plain integer
From: Wei Yongjun @ 2018-03-28 12:51 UTC (permalink / raw)
To: Doug Berger, Florian Fainelli; +Cc: Wei Yongjun, netdev, kernel-janitors
Fixes the following sparse warning:
drivers/net/ethernet/broadcom/genet/bcmgenet.c:1351:16: warning:
Using plain integer as NULL pointer
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 7db8edc..2f4cb5c 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -1348,7 +1348,7 @@ static struct sk_buff *bcmgenet_free_tx_cb(struct device *dev,
dma_unmap_addr_set(cb, dma_addr, 0);
}
- return 0;
+ return NULL;
}
/* Simple helper to free a receive control block's resources */
^ permalink raw reply related
* [PATCH net-next] net: hns3: remove unnecessary pci_set_drvdata() and devm_kfree()
From: Wei Yongjun @ 2018-03-28 12:51 UTC (permalink / raw)
To: Yisen Zhuang, Salil Mehta; +Cc: Wei Yongjun, netdev, kernel-janitors
The devm_kfree function allocates memory that is released when a
driver detaches. Also the driver core clears the driver data to NULL
after device release. So remove the unnecessary pci_set_drvdata()
and devm_kfree().
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index a31b4ad..8c55965 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -1614,10 +1614,6 @@ static void hns3_remove(struct pci_dev *pdev)
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
hnae3_unregister_ae_dev(ae_dev);
-
- devm_kfree(&pdev->dev, ae_dev);
-
- pci_set_drvdata(pdev, NULL);
}
static struct pci_driver hns3_driver = {
^ permalink raw reply related
* [PATCH net-next] ice: Fix error return code in ice_init_hw()
From: Wei Yongjun @ 2018-03-28 12:50 UTC (permalink / raw)
To: Jeff Kirsher; +Cc: Wei Yongjun, intel-wired-lan, netdev, kernel-janitors
Fix to return error code ICE_ERR_NO_MEMORY from the alloc error
handling case instead of 0, as done elsewhere in this function.
Fixes: dc49c7723676 ("ice: Get MAC/PHY/link info and scheduler topology")
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
---
drivers/net/ethernet/intel/ice/ice_common.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index 385f5d4..21977ec 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -468,8 +468,10 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
mac_buf_len = sizeof(struct ice_aqc_manage_mac_read_resp);
mac_buf = devm_kzalloc(ice_hw_to_dev(hw), mac_buf_len, GFP_KERNEL);
- if (!mac_buf)
+ if (!mac_buf) {
+ status = ICE_ERR_NO_MEMORY;
goto err_unroll_fltr_mgmt_struct;
+ }
status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
devm_kfree(ice_hw_to_dev(hw), mac_buf);
^ permalink raw reply related
* Re: [PATCH] net: fec: set dma_coherent_mask
From: Greg Ungerer @ 2018-03-28 12:29 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: netdev, Linux/m68k
In-Reply-To: <CAMuHMdXzySkpAi+kS+XCXR8kjY_AsV4h6t+XsuXx4o_0u2GSEA@mail.gmail.com>
Hi Geert,
On 28/03/18 17:57, Geert Uytterhoeven wrote:
[skip]
>> [PATCH] m68k: set dma and coherent masks for platform FEC ethernets
>>
>> As of commit 205e1b7f51e4 ("dma-mapping: warn when there is no
>> coherent_dma_mask") the Freescale FEC driver is issuing the following
>> warning on driver initialization on ColdFire systems:
>>
>> WARNING: CPU: 0 PID: 1 at ./include/linux/dma-mapping.h:516 0x40159e20
>> Modules linked in:
>> CPU: 0 PID: 1 Comm: swapper Not tainted 4.16.0-rc7-dirty #4
>> Stack from 41833dd8:
>> 41833dd8 40259c53 40025534 40279e26 00000003 00000000 4004e514 41827000
>> 400255de 40244e42 00000204 40159e20 00000009 00000000 00000000 4024531d
>> 40159e20 40244e42 00000204 00000000 00000000 00000000 00000007 00000000
>> 00000000 40279e26 4028d040 40226576 4003ae88 40279e26 418273f6 41833ef8
>> 7fffffff 418273f2 41867028 4003c9a2 4180ac6c 00000004 41833f8c 4013e71c
>> 40279e1c 40279e26 40226c16 4013ced2 40279e26 40279e58 4028d040 00000000
>> Call Trace:
>> [<40025534>] 0x40025534
>> [<4004e514>] 0x4004e514
>> [<400255de>] 0x400255de
>> [<40159e20>] 0x40159e20
>> [<40159e20>] 0x40159e20
>>
>> It is not fatal, the driver and the system continue to function normally.
>>
>> As per the warning the coherent_dma_mask is not set on this device.
>> There is nothing special about the DMA memory coherency on this hardware
>> so we can just set the mask to 32bits in the platform data for the FEC
>> ethernet devices.
>>
>> Signed-off-by: Greg Ungerer <gerg@linux-m68k.org>
>> ---
>> arch/m68k/coldfire/device.c | 14 ++++++++++++--
>> 1 file changed, 12 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/m68k/coldfire/device.c b/arch/m68k/coldfire/device.c
>> index 84938fd..f93e0e5 100644
>> --- a/arch/m68k/coldfire/device.c
>> +++ b/arch/m68k/coldfire/device.c
>> @@ -130,12 +130,18 @@
>> },
>> };
>>
>> +static u64 mcf_dma_mask = DMA_BIT_MASK(32);
>> +
>> static struct platform_device mcf_fec0 = {
>> .name = FEC_NAME,
>> .id = 0,
>> .num_resources = ARRAY_SIZE(mcf_fec0_resources),
>> .resource = mcf_fec0_resources,
>> - .dev.platform_data = FEC_PDATA,
>> + .dev = {
>> + .dma_mask = &mcf_dma_mask,
>
> Can you make this &mcf_fec0.dev.coherent_dma_mask, removing the need for
> mcf_dma_mask, or doesn't C allow that?
Yes, sure can. Looks like some other architectures do that too.
I'll change it. Thanks.
Regards
Greg
>> + .coherent_dma_mask = DMA_BIT_MASK(32),
>> + .platform_data = FEC_PDATA,
>> + }
>> };
>>
>> #ifdef MCFFEC_BASE1
>> @@ -167,7 +173,11 @@
>> .id = 1,
>> .num_resources = ARRAY_SIZE(mcf_fec1_resources),
>> .resource = mcf_fec1_resources,
>> - .dev.platform_data = FEC_PDATA,
>> + .dev = {
>> + .dma_mask = &mcf_dma_mask,
>
> Likewise.
>
>> + .coherent_dma_mask = DMA_BIT_MASK(32),
>> + .platform_data = FEC_PDATA,
>> + }
>
> Gr{oetje,eeting}s,
>
> Geert
>
^ permalink raw reply
* Re: [PATCH 3/7] net: thunderx: add multicast filter management support
From: kbuild test robot @ 2018-03-28 12:29 UTC (permalink / raw)
To: Vadim Lomovtsev
Cc: kbuild-all, sgoutham, sunil.kovvuri, robert.richter,
linux-arm-kernel, netdev, linux-kernel, dnelson, Vadim Lomovtsev
In-Reply-To: <20180327150736.10718-4-Vadim.Lomovtsev@caviumnetworks.com>
[-- Attachment #1: Type: text/plain, Size: 3695 bytes --]
Hi Vadim,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on net-next/master]
[also build test WARNING on v4.16-rc7 next-20180328]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Vadim-Lomovtsev/net-thunderx-implement-DMAC-filtering-support/20180328-190332
config: x86_64-randconfig-s1-03281908 (attached as .config)
compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All warnings (new ones prefixed by >>):
drivers/net/ethernet/cavium/thunder/thunder_bgx.c: In function 'bgx_lmac_save_filter':
>> drivers/net/ethernet/cavium/thunder/thunder_bgx.c:286:3: warning: 'return' with no value, in function returning non-void [-Wreturn-type]
return;
^~~~~~
drivers/net/ethernet/cavium/thunder/thunder_bgx.c:281:12: note: declared here
static int bgx_lmac_save_filter(struct lmac *lmac, u64 dmac, u8 vf_id)
^~~~~~~~~~~~~~~~~~~~
In file included from drivers/net/ethernet/cavium/thunder/nic.h:15:0,
from drivers/net/ethernet/cavium/thunder/thunder_bgx.c:21:
drivers/net/ethernet/cavium/thunder/thunder_bgx.c: In function 'bgx_set_dmac_cam_filter_mac':
>> drivers/net/ethernet/cavium/thunder/thunder_bgx.h:61:38: warning: left shift count >= width of type [-Wshift-count-overflow]
#define RX_DMACX_CAM_LMACID(x) (x << 49)
^
>> drivers/net/ethernet/cavium/thunder/thunder_bgx.c:324:8: note: in expansion of macro 'RX_DMACX_CAM_LMACID'
cfg = RX_DMACX_CAM_LMACID(lmacid & LMAC_ID_MASK) |
^~~~~~~~~~~~~~~~~~~
vim +/return +286 drivers/net/ethernet/cavium/thunder/thunder_bgx.c
280
> 281 static int bgx_lmac_save_filter(struct lmac *lmac, u64 dmac, u8 vf_id)
282 {
283 u8 i = 0;
284
285 if (!lmac)
> 286 return;
287
288 /* At the same time we could have several VFs 'attached' to some
289 * particular LMAC, and each VF is represented as network interface
290 * for kernel. So from user perspective it should be possible to
291 * manipulate with its' (VF) receive modes. However from PF
292 * driver perspective we need to keep track of filter configurations
293 * for different VFs to prevent filter values dupes
294 */
295 for (i = 0; i < lmac->dmacs_cfg; i++) {
296 if (lmac->dmacs[i].dmac == dmac) {
297 lmac->dmacs[i].vf_map |= BIT_ULL(vf_id);
298 return -1;
299 }
300 }
301
302 if (!(lmac->dmacs_cfg < lmac->dmacs_count))
303 return -1;
304
305 /* keep it for further tracking */
306 lmac->dmacs[lmac->dmacs_cfg].dmac = dmac;
307 lmac->dmacs[lmac->dmacs_cfg].vf_map = BIT_ULL(vf_id);
308 lmac->dmacs_cfg++;
309 return 0;
310 }
311
312 static int bgx_set_dmac_cam_filter_mac(struct bgx *bgx, int lmacid, u64 cam_dmac, u8 idx)
313 {
314 struct lmac *lmac = NULL;
315 u64 cfg = 0;
316
317 /* skip zero addresses as meaningless */
318 if (!cam_dmac || !bgx)
319 return -1;
320
321 lmac = &bgx->lmac[lmacid];
322
323 /* configure DCAM filtering for designated LMAC */
> 324 cfg = RX_DMACX_CAM_LMACID(lmacid & LMAC_ID_MASK) |
325 RX_DMACX_CAM_EN | cam_dmac;
326 bgx_reg_write(bgx, 0, BGX_CMR_RX_DMACX_CAM + ((lmacid * lmac->dmacs_count) + idx) * sizeof(u64), cfg);
327 return 0;
328 }
329
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 29217 bytes --]
^ permalink raw reply
* [PATCH net-next v3 5/5] qede: Ethtool flash update support.
From: Sudarsana Reddy Kalluru @ 2018-03-28 12:14 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, yuvalm
In-Reply-To: <20180328121423.7718-1-sudarsana.kalluru@cavium.com>
The patch adds ethtool callback implementation for flash update.
Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 4ca3847..ecbf1de 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -699,6 +699,14 @@ static u32 qede_get_link(struct net_device *dev)
return current_link.link_up;
}
+static int qede_flash_device(struct net_device *dev,
+ struct ethtool_flash *flash)
+{
+ struct qede_dev *edev = netdev_priv(dev);
+
+ return edev->ops->common->nvm_flash(edev->cdev, flash->data);
+}
+
static int qede_get_coalesce(struct net_device *dev,
struct ethtool_coalesce *coal)
{
@@ -1806,6 +1814,7 @@ static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata)
.get_tunable = qede_get_tunable,
.set_tunable = qede_set_tunable,
+ .flash_device = qede_flash_device,
};
static const struct ethtool_ops qede_vf_ethtool_ops = {
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v3 4/5] qed: Adapter flash update support.
From: Sudarsana Reddy Kalluru @ 2018-03-28 12:14 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, yuvalm
In-Reply-To: <20180328121423.7718-1-sudarsana.kalluru@cavium.com>
This patch adds the required driver support for updating the flash or
non volatile memory of the adapter. At highlevel, flash upgrade comprises
of reading the flash images from the input file, validating the images and
writing them to the respective paritions.
Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_main.c | 338 +++++++++++++++++++++++++++++
include/linux/qed/qed_if.h | 19 ++
2 files changed, 357 insertions(+)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 2783288..9854aa9 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -45,6 +45,7 @@
#include <linux/etherdevice.h>
#include <linux/vmalloc.h>
#include <linux/crash_dump.h>
+#include <linux/crc32.h>
#include <linux/qed/qed_if.h>
#include <linux/qed/qed_ll2_if.h>
@@ -1553,6 +1554,342 @@ static int qed_drain(struct qed_dev *cdev)
return 0;
}
+static u32 qed_nvm_flash_image_access_crc(struct qed_dev *cdev,
+ struct qed_nvm_image_att *nvm_image,
+ u32 *crc)
+{
+ u8 *buf = NULL;
+ int rc, j;
+ u32 val;
+
+ /* Allocate a buffer for holding the nvram image */
+ buf = kzalloc(nvm_image->length, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Read image into buffer */
+ rc = qed_mcp_nvm_read(cdev, nvm_image->start_addr,
+ buf, nvm_image->length);
+ if (rc) {
+ DP_ERR(cdev, "Failed reading image from nvm\n");
+ goto out;
+ }
+
+ /* Convert the buffer into big-endian format (excluding the
+ * closing 4 bytes of CRC).
+ */
+ for (j = 0; j < nvm_image->length - 4; j += 4) {
+ val = cpu_to_be32(*(u32 *)&buf[j]);
+ *(u32 *)&buf[j] = val;
+ }
+
+ /* Calc CRC for the "actual" image buffer, i.e. not including
+ * the last 4 CRC bytes.
+ */
+ *crc = (~cpu_to_be32(crc32(0xffffffff, buf, nvm_image->length - 4)));
+
+out:
+ kfree(buf);
+
+ return rc;
+}
+
+/* Binary file format -
+ * /----------------------------------------------------------------------\
+ * 0B | 0x4 [command index] |
+ * 4B | image_type | Options | Number of register settings |
+ * 8B | Value |
+ * 12B | Mask |
+ * 16B | Offset |
+ * \----------------------------------------------------------------------/
+ * There can be several Value-Mask-Offset sets as specified by 'Number of...'.
+ * Options - 0'b - Calculate & Update CRC for image
+ */
+static int qed_nvm_flash_image_access(struct qed_dev *cdev, const u8 **data,
+ bool *check_resp)
+{
+ struct qed_nvm_image_att nvm_image;
+ struct qed_hwfn *p_hwfn;
+ bool is_crc = false;
+ u32 image_type;
+ int rc = 0, i;
+ u16 len;
+
+ *data += 4;
+ image_type = **data;
+ p_hwfn = QED_LEADING_HWFN(cdev);
+ for (i = 0; i < p_hwfn->nvm_info.num_images; i++)
+ if (image_type == p_hwfn->nvm_info.image_att[i].image_type)
+ break;
+ if (i == p_hwfn->nvm_info.num_images) {
+ DP_ERR(cdev, "Failed to find nvram image of type %08x\n",
+ image_type);
+ return -ENOENT;
+ }
+
+ nvm_image.start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
+ nvm_image.length = p_hwfn->nvm_info.image_att[i].len;
+
+ DP_VERBOSE(cdev, NETIF_MSG_DRV,
+ "Read image %02x; type = %08x; NVM [%08x,...,%08x]\n",
+ **data, image_type, nvm_image.start_addr,
+ nvm_image.start_addr + nvm_image.length - 1);
+ (*data)++;
+ is_crc = !!(**data & BIT(0));
+ (*data)++;
+ len = *((u16 *)*data);
+ *data += 2;
+ if (is_crc) {
+ u32 crc = 0;
+
+ rc = qed_nvm_flash_image_access_crc(cdev, &nvm_image, &crc);
+ if (rc) {
+ DP_ERR(cdev, "Failed calculating CRC, rc = %d\n", rc);
+ goto exit;
+ }
+
+ rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM,
+ (nvm_image.start_addr +
+ nvm_image.length - 4), (u8 *)&crc, 4);
+ if (rc)
+ DP_ERR(cdev, "Failed writing to %08x, rc = %d\n",
+ nvm_image.start_addr + nvm_image.length - 4, rc);
+ goto exit;
+ }
+
+ /* Iterate over the values for setting */
+ while (len) {
+ u32 offset, mask, value, cur_value;
+ u8 buf[4];
+
+ value = *((u32 *)*data);
+ *data += 4;
+ mask = *((u32 *)*data);
+ *data += 4;
+ offset = *((u32 *)*data);
+ *data += 4;
+
+ rc = qed_mcp_nvm_read(cdev, nvm_image.start_addr + offset, buf,
+ 4);
+ if (rc) {
+ DP_ERR(cdev, "Failed reading from %08x\n",
+ nvm_image.start_addr + offset);
+ goto exit;
+ }
+
+ cur_value = le32_to_cpu(*((__le32 *)buf));
+ DP_VERBOSE(cdev, NETIF_MSG_DRV,
+ "NVM %08x: %08x -> %08x [Value %08x Mask %08x]\n",
+ nvm_image.start_addr + offset, cur_value,
+ (cur_value & ~mask) | (value & mask), value, mask);
+ value = (value & mask) | (cur_value & ~mask);
+ rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM,
+ nvm_image.start_addr + offset,
+ (u8 *)&value, 4);
+ if (rc) {
+ DP_ERR(cdev, "Failed writing to %08x\n",
+ nvm_image.start_addr + offset);
+ goto exit;
+ }
+
+ len--;
+ }
+exit:
+ return rc;
+}
+
+/* Binary file format -
+ * /----------------------------------------------------------------------\
+ * 0B | 0x3 [command index] |
+ * 4B | b'0: check_response? | b'1-31 reserved |
+ * 8B | File-type | reserved |
+ * \----------------------------------------------------------------------/
+ * Start a new file of the provided type
+ */
+static int qed_nvm_flash_image_file_start(struct qed_dev *cdev,
+ const u8 **data, bool *check_resp)
+{
+ int rc;
+
+ *data += 4;
+ *check_resp = !!(**data & BIT(0));
+ *data += 4;
+
+ DP_VERBOSE(cdev, NETIF_MSG_DRV,
+ "About to start a new file of type %02x\n", **data);
+ rc = qed_mcp_nvm_put_file_begin(cdev, **data);
+ *data += 4;
+
+ return rc;
+}
+
+/* Binary file format -
+ * /----------------------------------------------------------------------\
+ * 0B | 0x2 [command index] |
+ * 4B | Length in bytes |
+ * 8B | b'0: check_response? | b'1-31 reserved |
+ * 12B | Offset in bytes |
+ * 16B | Data ... |
+ * \----------------------------------------------------------------------/
+ * Write data as part of a file that was previously started. Data should be
+ * of length equal to that provided in the message
+ */
+static int qed_nvm_flash_image_file_data(struct qed_dev *cdev,
+ const u8 **data, bool *check_resp)
+{
+ u32 offset, len;
+ int rc;
+
+ *data += 4;
+ len = *((u32 *)(*data));
+ *data += 4;
+ *check_resp = !!(**data & BIT(0));
+ *data += 4;
+ offset = *((u32 *)(*data));
+ *data += 4;
+
+ DP_VERBOSE(cdev, NETIF_MSG_DRV,
+ "About to write File-data: %08x bytes to offset %08x\n",
+ len, offset);
+
+ rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_DATA, offset,
+ (char *)(*data), len);
+ *data += len;
+
+ return rc;
+}
+
+/* Binary file format [General header] -
+ * /----------------------------------------------------------------------\
+ * 0B | QED_NVM_SIGNATURE |
+ * 4B | Length in bytes |
+ * 8B | Highest command in this batchfile | Reserved |
+ * \----------------------------------------------------------------------/
+ */
+static int qed_nvm_flash_image_validate(struct qed_dev *cdev,
+ const struct firmware *image,
+ const u8 **data)
+{
+ u32 signature, len;
+
+ /* Check minimum size */
+ if (image->size < 12) {
+ DP_ERR(cdev, "Image is too short [%08x]\n", (u32)image->size);
+ return -EINVAL;
+ }
+
+ /* Check signature */
+ signature = *((u32 *)(*data));
+ if (signature != QED_NVM_SIGNATURE) {
+ DP_ERR(cdev, "Wrong signature '%08x'\n", signature);
+ return -EINVAL;
+ }
+
+ *data += 4;
+ /* Validate internal size equals the image-size */
+ len = *((u32 *)(*data));
+ if (len != image->size) {
+ DP_ERR(cdev, "Size mismatch: internal = %08x image = %08x\n",
+ len, (u32)image->size);
+ return -EINVAL;
+ }
+
+ *data += 4;
+ /* Make sure driver familiar with all commands necessary for this */
+ if (*((u16 *)(*data)) >= QED_NVM_FLASH_CMD_NVM_MAX) {
+ DP_ERR(cdev, "File contains unsupported commands [Need %04x]\n",
+ *((u16 *)(*data)));
+ return -EINVAL;
+ }
+
+ *data += 4;
+
+ return 0;
+}
+
+static int qed_nvm_flash(struct qed_dev *cdev, const char *name)
+{
+ const struct firmware *image;
+ const u8 *data, *data_end;
+ u32 cmd_type;
+ int rc;
+
+ rc = request_firmware(&image, name, &cdev->pdev->dev);
+ if (rc) {
+ DP_ERR(cdev, "Failed to find '%s'\n", name);
+ return rc;
+ }
+
+ DP_VERBOSE(cdev, NETIF_MSG_DRV,
+ "Flashing '%s' - firmware's data at %p, size is %08x\n",
+ name, image->data, (u32)image->size);
+ data = image->data;
+ data_end = data + image->size;
+
+ rc = qed_nvm_flash_image_validate(cdev, image, &data);
+ if (rc)
+ goto exit;
+
+ while (data < data_end) {
+ bool check_resp = false;
+
+ /* Parse the actual command */
+ cmd_type = *((u32 *)data);
+ switch (cmd_type) {
+ case QED_NVM_FLASH_CMD_FILE_DATA:
+ rc = qed_nvm_flash_image_file_data(cdev, &data,
+ &check_resp);
+ break;
+ case QED_NVM_FLASH_CMD_FILE_START:
+ rc = qed_nvm_flash_image_file_start(cdev, &data,
+ &check_resp);
+ break;
+ case QED_NVM_FLASH_CMD_NVM_CHANGE:
+ rc = qed_nvm_flash_image_access(cdev, &data,
+ &check_resp);
+ break;
+ default:
+ DP_ERR(cdev, "Unknown command %08x\n", cmd_type);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ if (rc) {
+ DP_ERR(cdev, "Command %08x failed\n", cmd_type);
+ goto exit;
+ }
+
+ /* Check response if needed */
+ if (check_resp) {
+ u32 mcp_response = 0;
+
+ if (qed_mcp_nvm_resp(cdev, (u8 *)&mcp_response)) {
+ DP_ERR(cdev, "Failed getting MCP response\n");
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ switch (mcp_response & FW_MSG_CODE_MASK) {
+ case FW_MSG_CODE_OK:
+ case FW_MSG_CODE_NVM_OK:
+ case FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK:
+ case FW_MSG_CODE_PHY_OK:
+ break;
+ default:
+ DP_ERR(cdev, "MFW returns error: %08x\n",
+ mcp_response);
+ rc = -EINVAL;
+ goto exit;
+ }
+ }
+ }
+
+exit:
+ release_firmware(image);
+
+ return rc;
+}
+
static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type,
u8 *buf, u16 len)
{
@@ -1719,6 +2056,7 @@ static int qed_update_mtu(struct qed_dev *cdev, u16 mtu)
.dbg_all_data_size = &qed_dbg_all_data_size,
.chain_alloc = &qed_chain_alloc,
.chain_free = &qed_chain_free,
+ .nvm_flash = &qed_nvm_flash,
.nvm_get_image = &qed_nvm_get_image,
.set_coalesce = &qed_set_coalesce,
.set_led = &qed_set_led,
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index 15e398c..b5b2bc9 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -483,6 +483,15 @@ struct qed_int_info {
u8 used_cnt;
};
+#define QED_NVM_SIGNATURE 0x12435687
+
+enum qed_nvm_flash_cmd {
+ QED_NVM_FLASH_CMD_FILE_DATA = 0x2,
+ QED_NVM_FLASH_CMD_FILE_START = 0x3,
+ QED_NVM_FLASH_CMD_NVM_CHANGE = 0x4,
+ QED_NVM_FLASH_CMD_NVM_MAX,
+};
+
struct qed_common_cb_ops {
void (*arfs_filter_op)(void *dev, void *fltr, u8 fw_rc);
void (*link_update)(void *dev,
@@ -658,6 +667,16 @@ struct qed_common_ops {
struct qed_chain *p_chain);
/**
+ * @brief nvm_flash - Flash nvm data.
+ *
+ * @param cdev
+ * @param name - file containing the data
+ *
+ * @return 0 on success, error otherwise.
+ */
+ int (*nvm_flash)(struct qed_dev *cdev, const char *name);
+
+/**
* @brief nvm_get_image - reads an entire image from nvram
*
* @param cdev
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v3 3/5] qed: Add APIs for flash access.
From: Sudarsana Reddy Kalluru @ 2018-03-28 12:14 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, yuvalm
In-Reply-To: <20180328121423.7718-1-sudarsana.kalluru@cavium.com>
This patch adds APIs for flash access.
Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed.h | 7 ++
drivers/net/ethernet/qlogic/qed/qed_hsi.h | 7 +-
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 121 ++++++++++++++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 34 +++++++++
4 files changed, 168 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index b409499..e07460a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -81,6 +81,13 @@ enum qed_coalescing_mode {
QED_COAL_MODE_ENABLE
};
+enum qed_nvm_cmd {
+ QED_PUT_FILE_BEGIN = DRV_MSG_CODE_NVM_PUT_FILE_BEGIN,
+ QED_PUT_FILE_DATA = DRV_MSG_CODE_NVM_PUT_FILE_DATA,
+ QED_NVM_WRITE_NVRAM = DRV_MSG_CODE_NVM_WRITE_NVRAM,
+ QED_GET_MCP_NVM_RESP = 0xFFFFFF00
+};
+
struct qed_eth_cb_ops;
struct qed_dev_info;
union qed_mcp_protocol_stats;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index de873d7..ea3cfe9 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -12210,8 +12210,11 @@ struct public_drv_mb {
#define DRV_MSG_CODE_VF_DISABLED_DONE 0xc0000000
#define DRV_MSG_CODE_CFG_VF_MSIX 0xc0010000
#define DRV_MSG_CODE_CFG_PF_VFS_MSIX 0xc0020000
+#define DRV_MSG_CODE_NVM_PUT_FILE_BEGIN 0x00010000
+#define DRV_MSG_CODE_NVM_PUT_FILE_DATA 0x00020000
#define DRV_MSG_CODE_NVM_GET_FILE_ATT 0x00030000
#define DRV_MSG_CODE_NVM_READ_NVRAM 0x00050000
+#define DRV_MSG_CODE_NVM_WRITE_NVRAM 0x00060000
#define DRV_MSG_CODE_MCP_RESET 0x00090000
#define DRV_MSG_CODE_SET_VERSION 0x000f0000
#define DRV_MSG_CODE_MCP_HALT 0x00100000
@@ -12265,7 +12268,6 @@ struct public_drv_mb {
#define DRV_MSG_CODE_FEATURE_SUPPORT 0x00300000
#define DRV_MSG_CODE_GET_MFW_FEATURE_SUPPORT 0x00310000
-
#define DRV_MSG_SEQ_NUMBER_MASK 0x0000ffff
u32 drv_mb_param;
@@ -12377,7 +12379,10 @@ struct public_drv_mb {
#define FW_MSG_CODE_DRV_CFG_VF_MSIX_DONE 0xb0010000
#define FW_MSG_CODE_NVM_OK 0x00010000
+#define FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK 0x00400000
+#define FW_MSG_CODE_PHY_OK 0x00110000
#define FW_MSG_CODE_OK 0x00160000
+#define FW_MSG_CODE_ERROR 0x00170000
#define FW_MSG_CODE_OS_WOL_SUPPORTED 0x00800000
#define FW_MSG_CODE_OS_WOL_NOT_SUPPORTED 0x00810000
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 2519e71..ec0d425 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -569,6 +569,31 @@ int qed_mcp_cmd(struct qed_hwfn *p_hwfn,
return 0;
}
+int qed_mcp_nvm_wr_cmd(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 cmd,
+ u32 param,
+ u32 *o_mcp_resp,
+ u32 *o_mcp_param, u32 i_txn_size, u32 *i_buf)
+{
+ struct qed_mcp_mb_params mb_params;
+ int rc;
+
+ memset(&mb_params, 0, sizeof(mb_params));
+ mb_params.cmd = cmd;
+ mb_params.param = param;
+ mb_params.p_data_src = i_buf;
+ mb_params.data_src_size = (u8)i_txn_size;
+ rc = qed_mcp_cmd_and_union(p_hwfn, p_ptt, &mb_params);
+ if (rc)
+ return rc;
+
+ *o_mcp_resp = mb_params.mcp_resp;
+ *o_mcp_param = mb_params.mcp_param;
+
+ return 0;
+}
+
int qed_mcp_nvm_rd_cmd(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
u32 cmd,
@@ -2261,6 +2286,102 @@ int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len)
return rc;
}
+int qed_mcp_nvm_resp(struct qed_dev *cdev, u8 *p_buf)
+{
+ struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *p_ptt;
+
+ p_ptt = qed_ptt_acquire(p_hwfn);
+ if (!p_ptt)
+ return -EBUSY;
+
+ memcpy(p_buf, &cdev->mcp_nvm_resp, sizeof(cdev->mcp_nvm_resp));
+ qed_ptt_release(p_hwfn, p_ptt);
+
+ return 0;
+}
+
+int qed_mcp_nvm_put_file_begin(struct qed_dev *cdev, u32 addr)
+{
+ struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *p_ptt;
+ u32 resp, param;
+ int rc;
+
+ p_ptt = qed_ptt_acquire(p_hwfn);
+ if (!p_ptt)
+ return -EBUSY;
+ rc = qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_NVM_PUT_FILE_BEGIN, addr,
+ &resp, ¶m);
+ cdev->mcp_nvm_resp = resp;
+ qed_ptt_release(p_hwfn, p_ptt);
+
+ return rc;
+}
+
+int qed_mcp_nvm_write(struct qed_dev *cdev,
+ u32 cmd, u32 addr, u8 *p_buf, u32 len)
+{
+ u32 buf_idx = 0, buf_size, nvm_cmd, nvm_offset, resp = 0, param;
+ struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+ struct qed_ptt *p_ptt;
+ int rc = -EINVAL;
+
+ p_ptt = qed_ptt_acquire(p_hwfn);
+ if (!p_ptt)
+ return -EBUSY;
+
+ switch (cmd) {
+ case QED_PUT_FILE_DATA:
+ nvm_cmd = DRV_MSG_CODE_NVM_PUT_FILE_DATA;
+ break;
+ case QED_NVM_WRITE_NVRAM:
+ nvm_cmd = DRV_MSG_CODE_NVM_WRITE_NVRAM;
+ break;
+ default:
+ DP_NOTICE(p_hwfn, "Invalid nvm write command 0x%x\n", cmd);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ while (buf_idx < len) {
+ buf_size = min_t(u32, (len - buf_idx), MCP_DRV_NVM_BUF_LEN);
+ nvm_offset = ((buf_size << DRV_MB_PARAM_NVM_LEN_OFFSET) |
+ addr) + buf_idx;
+ rc = qed_mcp_nvm_wr_cmd(p_hwfn, p_ptt, nvm_cmd, nvm_offset,
+ &resp, ¶m, buf_size,
+ (u32 *)&p_buf[buf_idx]);
+ if (rc) {
+ DP_NOTICE(cdev, "nvm write failed, rc = %d\n", rc);
+ resp = FW_MSG_CODE_ERROR;
+ break;
+ }
+
+ if (resp != FW_MSG_CODE_OK &&
+ resp != FW_MSG_CODE_NVM_OK &&
+ resp != FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK) {
+ DP_NOTICE(cdev,
+ "nvm write failed, resp = 0x%08x\n", resp);
+ rc = -EINVAL;
+ break;
+ }
+
+ /* This can be a lengthy process, and it's possible scheduler
+ * isn't pre-emptable. Sleep a bit to prevent CPU hogging.
+ */
+ if (buf_idx % 0x1000 > (buf_idx + buf_size) % 0x1000)
+ usleep_range(1000, 2000);
+
+ buf_idx += buf_size;
+ }
+
+ cdev->mcp_nvm_resp = resp;
+out:
+ qed_ptt_release(p_hwfn, p_ptt);
+
+ return rc;
+}
+
int qed_mcp_bist_register_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
u32 drv_mb_param = 0, rsp, param;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index 7d33354..8a5c988 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -443,6 +443,40 @@ int qed_mcp_set_led(struct qed_hwfn *p_hwfn,
*/
int qed_mcp_nvm_read(struct qed_dev *cdev, u32 addr, u8 *p_buf, u32 len);
+/**
+ * @brief Write to nvm
+ *
+ * @param cdev
+ * @param addr - nvm offset
+ * @param cmd - nvm command
+ * @param p_buf - nvm write buffer
+ * @param len - buffer len
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_nvm_write(struct qed_dev *cdev,
+ u32 cmd, u32 addr, u8 *p_buf, u32 len);
+
+/**
+ * @brief Put file begin
+ *
+ * @param cdev
+ * @param addr - nvm offset
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_nvm_put_file_begin(struct qed_dev *cdev, u32 addr);
+
+/**
+ * @brief Check latest response
+ *
+ * @param cdev
+ * @param p_buf - nvm write buffer
+ *
+ * @return int - 0 - operation was successful.
+ */
+int qed_mcp_nvm_resp(struct qed_dev *cdev, u8 *p_buf);
+
struct qed_nvm_image_att {
u32 start_addr;
u32 length;
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v3 2/5] qed: Fix PTT entry leak in the selftest error flow.
From: Sudarsana Reddy Kalluru @ 2018-03-28 12:14 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, yuvalm
In-Reply-To: <20180328121423.7718-1-sudarsana.kalluru@cavium.com>
Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed_selftest.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_selftest.c b/drivers/net/ethernet/qlogic/qed/qed_selftest.c
index b88082f..cf1d447 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_selftest.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_selftest.c
@@ -128,7 +128,8 @@ int qed_selftest_nvram(struct qed_dev *cdev)
rc = qed_mcp_bist_nvm_get_num_images(p_hwfn, p_ptt, &num_images);
if (rc || !num_images) {
DP_ERR(p_hwfn, "Failed getting number of images\n");
- return -EINVAL;
+ rc = -EINVAL;
+ goto err0;
}
/* Iterate over images and validate CRC */
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next v3 0/5] qed*: Flash upgrade support.
From: Sudarsana Reddy Kalluru @ 2018-03-28 12:14 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, yuvalm, Sudarsana Reddy Kalluru
From: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
The patch series adds adapter flash upgrade support for qed/qede drivers.
Please consider applying it to net-next branch.
Sudarsana Reddy Kalluru (5):
qed: Populate nvm image attribute shadow.
qed: Fix PTT entry leak in the selftest error flow.
qed: Add APIs for flash access.
qed: Adapter flash update support.
qede: Ethtool flash update support.
drivers/net/ethernet/qlogic/qed/qed.h | 15 ++
drivers/net/ethernet/qlogic/qed/qed_dev.c | 24 +-
drivers/net/ethernet/qlogic/qed/qed_hsi.h | 7 +-
drivers/net/ethernet/qlogic/qed/qed_main.c | 338 ++++++++++++++++++++++++
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 219 +++++++++++++--
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 56 +++-
drivers/net/ethernet/qlogic/qed/qed_selftest.c | 9 +-
drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 9 +
include/linux/qed/qed_if.h | 19 ++
9 files changed, 656 insertions(+), 40 deletions(-)
--
1.8.3.1
^ permalink raw reply
* [PATCH net-next v3 1/5] qed: Populate nvm image attribute shadow.
From: Sudarsana Reddy Kalluru @ 2018-03-28 12:14 UTC (permalink / raw)
To: davem; +Cc: netdev, Ariel.Elior, yuvalm
In-Reply-To: <20180328121423.7718-1-sudarsana.kalluru@cavium.com>
This patch adds support for populating the flash image attributes.
Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
drivers/net/ethernet/qlogic/qed/qed.h | 8 +++
drivers/net/ethernet/qlogic/qed/qed_dev.c | 24 ++++++-
drivers/net/ethernet/qlogic/qed/qed_mcp.c | 98 +++++++++++++++++++-------
drivers/net/ethernet/qlogic/qed/qed_mcp.h | 22 ++++--
drivers/net/ethernet/qlogic/qed/qed_selftest.c | 6 +-
5 files changed, 120 insertions(+), 38 deletions(-)
diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
index 6948855..b409499 100644
--- a/drivers/net/ethernet/qlogic/qed/qed.h
+++ b/drivers/net/ethernet/qlogic/qed/qed.h
@@ -437,6 +437,11 @@ enum BAR_ID {
BAR_ID_1 /* Used for doorbells */
};
+struct qed_nvm_image_info {
+ u32 num_images;
+ struct bist_nvm_image_att *image_att;
+};
+
#define DRV_MODULE_VERSION \
__stringify(QED_MAJOR_VERSION) "." \
__stringify(QED_MINOR_VERSION) "." \
@@ -561,6 +566,9 @@ struct qed_hwfn {
/* L2-related */
struct qed_l2_info *p_l2_info;
+ /* Nvm images number and attributes */
+ struct qed_nvm_image_info nvm_info;
+
struct qed_ptt *p_arfs_ptt;
struct qed_simd_fp_handler simd_proto_handler[64];
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 553a6d1..7ddec55 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -2930,6 +2930,12 @@ static int qed_get_dev_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
return 0;
}
+static void qed_nvm_info_free(struct qed_hwfn *p_hwfn)
+{
+ kfree(p_hwfn->nvm_info.image_att);
+ p_hwfn->nvm_info.image_att = NULL;
+}
+
static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
void __iomem *p_regview,
void __iomem *p_doorbells,
@@ -2993,12 +2999,25 @@ static int qed_hw_prepare_single(struct qed_hwfn *p_hwfn,
DP_NOTICE(p_hwfn, "Failed to initiate PF FLR\n");
}
+ /* NVRAM info initialization and population */
+ if (IS_LEAD_HWFN(p_hwfn)) {
+ rc = qed_mcp_nvm_info_populate(p_hwfn);
+ if (rc) {
+ DP_NOTICE(p_hwfn,
+ "Failed to populate nvm info shadow\n");
+ goto err2;
+ }
+ }
+
/* Allocate the init RT array and initialize the init-ops engine */
rc = qed_init_alloc(p_hwfn);
if (rc)
- goto err2;
+ goto err3;
return rc;
+err3:
+ if (IS_LEAD_HWFN(p_hwfn))
+ qed_nvm_info_free(p_hwfn);
err2:
if (IS_LEAD_HWFN(p_hwfn))
qed_iov_free_hw_info(p_hwfn->cdev);
@@ -3054,6 +3073,7 @@ int qed_hw_prepare(struct qed_dev *cdev,
if (rc) {
if (IS_PF(cdev)) {
qed_init_free(p_hwfn);
+ qed_nvm_info_free(p_hwfn);
qed_mcp_free(p_hwfn);
qed_hw_hwfn_free(p_hwfn);
}
@@ -3086,6 +3106,8 @@ void qed_hw_remove(struct qed_dev *cdev)
}
qed_iov_free_hw_info(cdev);
+
+ qed_nvm_info_free(p_hwfn);
}
static void qed_chain_free_next_ptr(struct qed_dev *cdev,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 6f46cb1..2519e71 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -2303,9 +2303,9 @@ int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
return rc;
}
-int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn,
- struct qed_ptt *p_ptt,
- u32 *num_images)
+int qed_mcp_bist_nvm_get_num_images(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 *num_images)
{
u32 drv_mb_param = 0, rsp;
int rc = 0;
@@ -2324,10 +2324,10 @@ int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn,
return rc;
}
-int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
- struct qed_ptt *p_ptt,
- struct bist_nvm_image_att *p_image_att,
- u32 image_index)
+int qed_mcp_bist_nvm_get_image_att(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct bist_nvm_image_att *p_image_att,
+ u32 image_index)
{
u32 buf_size = 0, param, resp = 0, resp_param = 0;
int rc;
@@ -2351,16 +2351,71 @@ int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
return rc;
}
+int qed_mcp_nvm_info_populate(struct qed_hwfn *p_hwfn)
+{
+ struct qed_nvm_image_info *nvm_info = &p_hwfn->nvm_info;
+ struct qed_ptt *p_ptt;
+ int rc;
+ u32 i;
+
+ p_ptt = qed_ptt_acquire(p_hwfn);
+ if (!p_ptt) {
+ DP_ERR(p_hwfn, "failed to acquire ptt\n");
+ return -EBUSY;
+ }
+
+ /* Acquire from MFW the amount of available images */
+ nvm_info->num_images = 0;
+ rc = qed_mcp_bist_nvm_get_num_images(p_hwfn,
+ p_ptt, &nvm_info->num_images);
+ if (rc == -EOPNOTSUPP) {
+ DP_INFO(p_hwfn, "DRV_MSG_CODE_BIST_TEST is not supported\n");
+ goto out;
+ } else if (rc || !nvm_info->num_images) {
+ DP_ERR(p_hwfn, "Failed getting number of images\n");
+ goto err0;
+ }
+
+ nvm_info->image_att = kmalloc(nvm_info->num_images *
+ sizeof(struct bist_nvm_image_att),
+ GFP_KERNEL);
+ if (!nvm_info->image_att) {
+ rc = -ENOMEM;
+ goto err0;
+ }
+
+ /* Iterate over images and get their attributes */
+ for (i = 0; i < nvm_info->num_images; i++) {
+ rc = qed_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
+ &nvm_info->image_att[i], i);
+ if (rc) {
+ DP_ERR(p_hwfn,
+ "Failed getting image index %d attributes\n", i);
+ goto err1;
+ }
+
+ DP_VERBOSE(p_hwfn, QED_MSG_SP, "image index %d, size %x\n", i,
+ nvm_info->image_att[i].len);
+ }
+out:
+ qed_ptt_release(p_hwfn, p_ptt);
+ return 0;
+
+err1:
+ kfree(nvm_info->image_att);
+err0:
+ qed_ptt_release(p_hwfn, p_ptt);
+ return rc;
+}
+
static int
qed_mcp_get_nvm_image_att(struct qed_hwfn *p_hwfn,
struct qed_ptt *p_ptt,
enum qed_nvm_images image_id,
struct qed_nvm_image_att *p_image_att)
{
- struct bist_nvm_image_att mfw_image_att;
enum nvm_image_type type;
- u32 num_images, i;
- int rc;
+ u32 i;
/* Translate image_id into MFW definitions */
switch (image_id) {
@@ -2376,29 +2431,18 @@ int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
return -EINVAL;
}
- /* Learn number of images, then traverse and see if one fits */
- rc = qed_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
- if (rc || !num_images)
- return -EINVAL;
-
- for (i = 0; i < num_images; i++) {
- rc = qed_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
- &mfw_image_att, i);
- if (rc)
- return rc;
-
- if (type == mfw_image_att.image_type)
+ for (i = 0; i < p_hwfn->nvm_info.num_images; i++)
+ if (type == p_hwfn->nvm_info.image_att[i].image_type)
break;
- }
- if (i == num_images) {
+ if (i == p_hwfn->nvm_info.num_images) {
DP_VERBOSE(p_hwfn, QED_MSG_STORAGE,
"Failed to find nvram image of type %08x\n",
image_id);
- return -EINVAL;
+ return -ENOENT;
}
- p_image_att->start_addr = mfw_image_att.nvm_start_addr;
- p_image_att->length = mfw_image_att.len;
+ p_image_att->start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
+ p_image_att->length = p_hwfn->nvm_info.image_att[i].len;
return 0;
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
index c7ec239..7d33354 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
@@ -496,9 +496,9 @@ int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn,
*
* @return int - 0 - operation was successful.
*/
-int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn,
- struct qed_ptt *p_ptt,
- u32 *num_images);
+int qed_mcp_bist_nvm_get_num_images(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ u32 *num_images);
/**
* @brief Bist nvm test - get image attributes by index
@@ -510,10 +510,10 @@ int qed_mcp_bist_nvm_test_get_num_images(struct qed_hwfn *p_hwfn,
*
* @return int - 0 - operation was successful.
*/
-int qed_mcp_bist_nvm_test_get_image_att(struct qed_hwfn *p_hwfn,
- struct qed_ptt *p_ptt,
- struct bist_nvm_image_att *p_image_att,
- u32 image_index);
+int qed_mcp_bist_nvm_get_image_att(struct qed_hwfn *p_hwfn,
+ struct qed_ptt *p_ptt,
+ struct bist_nvm_image_att *p_image_att,
+ u32 image_index);
/* Using hwfn number (and not pf_num) is required since in CMT mode,
* same pf_num may be used by two different hwfn
@@ -957,4 +957,12 @@ void qed_mcp_resc_lock_default_init(struct qed_resc_lock_params *p_lock,
* @param p_ptt
*/
int qed_mcp_set_capabilities(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);
+
+/**
+ * @brief Populate the nvm info shadow in the given hardware function
+ *
+ * @param p_hwfn
+ */
+int qed_mcp_nvm_info_populate(struct qed_hwfn *p_hwfn);
+
#endif
diff --git a/drivers/net/ethernet/qlogic/qed/qed_selftest.c b/drivers/net/ethernet/qlogic/qed/qed_selftest.c
index 1bafc05..b88082f 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_selftest.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_selftest.c
@@ -125,7 +125,7 @@ int qed_selftest_nvram(struct qed_dev *cdev)
}
/* Acquire from MFW the amount of available images */
- rc = qed_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
+ rc = qed_mcp_bist_nvm_get_num_images(p_hwfn, p_ptt, &num_images);
if (rc || !num_images) {
DP_ERR(p_hwfn, "Failed getting number of images\n");
return -EINVAL;
@@ -136,8 +136,8 @@ int qed_selftest_nvram(struct qed_dev *cdev)
/* This mailbox returns information about the image required for
* reading it.
*/
- rc = qed_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
- &image_att, i);
+ rc = qed_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
+ &image_att, i);
if (rc) {
DP_ERR(p_hwfn,
"Failed getting image index %d attributes\n",
--
1.8.3.1
^ permalink raw reply related
* ipv6: stable request
From: Denys Zagorui @ 2018-03-28 11:45 UTC (permalink / raw)
To: netdev; +Cc: edumazet, davem
12d94a804946af291e24b80fc53ec86264765781
<https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/commit/?h=v4.14.29&id=12d94a804946af291e24b80fc53ec86264765781>
ipv6: fix NULL dereference in ip6_route_dev_notify()
This BUG touches 4.1 4.4 4.9.
^ permalink raw reply
* Re: [iproute PATCH] man: ip-route.8: ssthresh parameter is NUMBER
From: Simon Horman @ 2018-03-28 11:52 UTC (permalink / raw)
To: Phil Sutter; +Cc: Stephen Hemminger, netdev
In-Reply-To: <20180322140038.21369-1-phil@nwl.cc>
On Thu, Mar 22, 2018 at 03:00:38PM +0100, Phil Sutter wrote:
> Synopsis section was inconsistent with regards to help text and later
> description of ssthresh parameter.
>
> Signed-off-by: Phil Sutter <phil@nwl.cc>
Reviewed-by: Simon Horman <simon.horman@netronome.com>
^ permalink raw reply
* [PATCH] test_bpf: Fix NULL vs IS_ERR() check in test_skb_segment()
From: Dan Carpenter @ 2018-03-28 11:48 UTC (permalink / raw)
To: Alexei Starovoitov, Yonghong Song
Cc: Daniel Borkmann, netdev, kernel-janitors
The skb_segment() function returns error pointers on error. It never
returns NULL.
Fixes: 76db8087c4c9 ("net: bpf: add a test for skb_segment in test_bpf module")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
diff --git a/lib/test_bpf.c b/lib/test_bpf.c
index b2badf6b23cd..8e157806df7a 100644
--- a/lib/test_bpf.c
+++ b/lib/test_bpf.c
@@ -6649,7 +6649,7 @@ static __init int test_skb_segment(void)
}
segs = skb_segment(skb, features);
- if (segs) {
+ if (!IS_ERR(segs)) {
kfree_skb_list(segs);
ret = 0;
pr_info("%s: success in skb_segment!", __func__);
^ permalink raw reply related
* Re: RFC on writel and writel_relaxed
From: okaya @ 2018-03-28 11:41 UTC (permalink / raw)
To: Linus Torvalds
Cc: Benjamin Herrenschmidt, Alexander Duyck, Will Deacon,
Arnd Bergmann, Jason Gunthorpe, David Laight, Oliver,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT), linux-rdma,
Alexander Duyck, Paul E. McKenney, netdev, linus971
In-Reply-To: <CA+55aFxULkhZGhg-tTBBxBBvXbL7QV7f6zvwW7U2wHFijqGEqw@mail.gmail.com>
On 2018-03-28 02:14, Linus Torvalds wrote:
> On Tue, Mar 27, 2018 at 5:24 PM, Sinan Kaya <okaya@codeaurora.org>
> wrote:
>>
>> Basically changing it to
>>
>> dma_buffer->foo = 1; /* WB */
>> wmb()
>> writel_relaxed(KICK, DMA_KICK_REGISTER); /* UC */
>> mmiowb()
>
> Why?
>
> Why not just remove the wmb(), and keep the barrier in the writel()?
Yes, we want to get there indeed. It is because of some arch not
implementing writel properly. Maintainers want to play safe.
That is why I asked if IA64 and other well known archs follow the
strongly ordered rule at this moment like PPC and ARM.
Or should we go and inform every arch about this before yanking wmb()?
Maintainers are afraid of introducing a regression.
>
> The above code makes no sense, and just looks stupid to me. It also
> generates pointlessly bad code on x86, so it's bad there too.
>
> Linus
^ permalink raw reply
* RE: RFC on writel and writel_relaxed
From: David Laight @ 2018-03-28 11:30 UTC (permalink / raw)
To: 'Benjamin Herrenschmidt', Will Deacon
Cc: Linus Torvalds, Alexander Duyck, Sinan Kaya, Arnd Bergmann,
Jason Gunthorpe, Oliver,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
linux-rdma@vger.kernel.org, Paul E. McKenney,
netdev@vger.kernel.org
In-Reply-To: <1522230988.21446.7.camel@kernel.crashing.org>
From: Benjamin Herrenschmidt
> Sent: 28 March 2018 10:56
...
> For example, let's say I have a device with a reset bit and the spec
> says the reset bit needs to be set for at least 10us.
>
> This is wrong:
>
> writel(1, RESET_REG);
> usleep(10);
> writel(0, RESET_REG);
>
> Because of write posting, the first write might arrive to the device
> right before the second one.
>
> The typical "fix" is to turn that into:
>
> writel(1, RESET_REG);
> readl(RESET_REG); /* Flush posted writes */
Would a writel(1, RESET_REG) here provide enough synchronsiation?
> usleep(10);
> writel(0, RESET_REG);
>
> *However* the issue here, at least on power, is that the CPU can issue
> that readl but doesn't necessarily wait for it to complete (ie, the
> data to return), before proceeding to the usleep. Now a usleep contains
> a bunch of loads and stores and is probably fine, but a udelay which
> just loops on the timebase may not be.
>
> Thus we may still violate the timing requirement.
I've seem that sort of code (with udelay() and no read back) quite often.
How many were in linux I don't know.
For small delays I usually fix it by repeated writes (of the same value)
to the device register. That can guarantee very short intervals.
The only time I've actually seen buffered writes break timing was
between a 286 and an 8859 interrupt controller.
If you wrote to the mask then enabled interrupts the first IACK cycle
could be too close to write and break the cycle recovery time.
That clobbered most of the interrupt controller registers.
That probably affected every 286 board ever built!
Not sure how much software added the required extra bus cycle.
> What we did inside readl, with the twi;isync sequence (which basically
> means, trap on return value with "trap never" as a condition, followed
> by isync that ensures all excpetion conditions are resolved), is force
> the CPU to "consume" the data from the read before moving on.
>
> This effectively makes readl fully synchronous (we would probably avoid
> that if we were to implement a readl_relaxed).
I've always wondered exactly what the twi;isync were for - always seemed
very heavy handed for most mmio reads.
Particularly if you are doing mmio reads from a data fifo.
Perhaps there should be a writel_wait() that is allowed to do a read back
for such code paths?
David
^ permalink raw reply
* Passing uninitialised local variable
From: Himanshu Jha @ 2018-03-28 11:20 UTC (permalink / raw)
To: arend.vanspriel, franky.lin, hante.meuleman, chi-hsien.lin,
wright.feng
Cc: kvalo, johannes.berg, linux-wireless, brcm80211-dev-list.pdl,
brcm80211-dev-list, netdev
Hello everyone,
I recently found that a local variable in passed uninitialised to the
function at
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:2950
u32 var;
err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var);
if (err) {
brcmf_err("wl dtim_assoc failed (%d)\n", err);
goto update_bss_info_out;
}
dtim_period = (u8)var;
Now, the brcmf_fil_iovar_int_get() is defined as:
s32
brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
{
__le32 data_le = cpu_to_le32(*data);
s32 err;
err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le));
if (err == 0)
*data = le32_to_cpu(data_le);
return err;
}
We can cleary see that 'var' in used uninitialised in the very first line
which is an undefined behavior.
So, what could be a possible fix for the above ?
I'm not sure initialising 'var' to 0 would be the correct solution.
--
Thanks
Himanshu Jha
^ permalink raw reply
* 4.14.29 - tcp_push() - null skb's cb dereference
From: Krzysztof Blaszkowski @ 2018-03-28 10:51 UTC (permalink / raw)
To: netdev
Hi,
I noticed a kernel bug report like below:
[95576.826393] BUG: unable to handle kernel NULL pointer dereference at
0000000000000038
[95576.834296] IP: tcp_push+0x3d/0x110
[95576.837829] PGD 2c8474067 P4D 2c8474067 PUD 1119cf067 PMD 0
[95576.843536] Oops: 0002 [#1] SMP NOPTI
[95576.847247] CPU: 3 PID: 1682 Comm: nginx Not tainted 4.14.29 #1
[95576.854421] Hardware name: PC-FACTORY empty/Tyan Transport GT24-
B3992-E, BIOS 'V1.06.B10 ' 06/23/2009
[95576.863678] task: ffff9e4f150b2580 task.stack: ffffb21401a50000
[95576.869641] RIP: 0010:tcp_push+0x3d/0x110
[95576.873692] RSP: 0018:ffffb21401a53be0 EFLAGS: 00010246
[95576.878959] RAX: 0000000000000000 RBX: 0000000000009310 RCX:
0000000000000000
[95576.886133] RDX: 0000000000000001 RSI: 0000000000000040 RDI:
ffff9e4e79871f00
[95576.893306] RBP: ffffb21401a53c78 R08: 00000000000065d0 R09:
ffff9e4e79872048
[95576.900479] R10: 00000000000005a8 R11: 0000000000000000 R12:
00000000ffffffe0
[95576.907652] R13: ffffb21401a53cf8 R14: ffff9e4e79871f00 R15:
ffff9e4f68727100
[95576.914824] FS: 00007f683b4e1700(0000) GS:ffff9e50732c0000(0000)
knlGS:0000000000000000
[95576.922953] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[95576.928737] CR2: 0000000000000038 CR3: 000000020aa0e000 CR4:
00000000000006e0
[95576.935908] Call Trace:
[95576.938403] ? tcp_sendmsg_locked+0x60a/0xd90
[95576.942872] tcp_sendmsg+0x27/0x40
[95576.946386] inet_sendmsg+0x2c/0xa0
[95576.949987] sock_sendmsg+0x33/0x40
[95576.953587] sock_write_iter+0x76/0xd0
[95576.957448] do_iter_readv_writev+0x108/0x160
[95576.961917] do_iter_write+0x82/0x190
[95576.965690] vfs_writev+0xbb/0x120
[95576.969203] ? ep_poll+0x240/0x3f0
[95576.972714] do_writev+0x4d/0xd0
[95576.976052] ? do_writev+0x4d/0xd0
[95576.979564] SyS_writev+0xb/0x10
[95576.982905] do_syscall_64+0x5a/0x110
[95576.986678] entry_SYSCALL_64_after_hwframe+0x3d/0xa2
[95576.991838] RIP: 0033:0x7f6839e56170
[95576.995523] RSP: 002b:00007ffe34c9cf48 EFLAGS: 00000246 ORIG_RAX:
0000000000000014
[95577.003265] RAX: ffffffffffffffda RBX: 0000000004b622c0 RCX:
00007f6839e56170
[95577.010507] RDX: 0000000000000017 RSI: 00007ffe34c9cfd0 RDI:
0000000000000012
[95577.017749] RBP: 00007ffe34c9cfb0 R08: 00000000004b1c2f R09:
00007ffe34c9d130
[95577.024989] R10: 000000000001d6c2 R11: 0000000000000246 R12:
0000000002f3eec0
[95577.032228] R13: 000000007fffefff R14: 0000000000000000 R15:
0000000002f3eec0
[95577.039469] Code: 01 00 00 4c 8d 8f 48 01 00 00 41 89 d2 41 89 f3 89
ca b9 00 00 00 00 49 39 c1 48 0f 44 c1 41 81 e3 00 80 00 00 0f 85 ac 00
00 00 <80> 48 38 08 8b 8f 64 06 00 00 89 8f 6c 06 00 00 83 e6 01 74 0c
[95577.058617] RIP: tcp_push+0x3d/0x110 RSP: ffffb21401a53be0
[95577.064208] CR2: 0000000000000038
[95577.068056] ---[ end trace 19bfaf872fd3ef10 ]--
further report analysis ended up in net/ipv4/tcp.c :
(gdb) list *(tcp_push+0x3d)
0xfd is in tcp_push (/data/work/linux-4.14.29/net/ipv4/tcp.c:630).
625 }
626 EXPORT_SYMBOL(tcp_ioctl);
627
628 static inline void tcp_mark_push(struct tcp_sock *tp, struct
sk_buff *skb)
629 {
630 TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_PSH;
631 tp->pushed_seq = tp->write_seq;
632 }
and tcp_mark_push() is inlined in tcp_push() indeed.
Looking forward to seeing rationale for tcp_write_queue_tail(sk)
returning null skb - assuming the above is correct.
Thanks
^ permalink raw reply
* [PATCH v3] staging: fsl-dpaa2/ethsw: Fix tag control information value overwrite
From: Razvan Stefanescu @ 2018-03-28 10:50 UTC (permalink / raw)
To: gregkh
Cc: devel, andrew, netdev, alexandru.marginean, linux-kernel,
ioana.ciornei, laurentiu.tudor
The tag control information (TCI) part of the VLAN header contains several
fields, including PCP (priority code point) and PVID (port VLAN id).
Current implementation uses function ethsw_port_set_tci() to set the PVID
value and mistakenly overwrites the rest of the TCI fields with 0,
including PCP which by default has a value of 7.
Fix this by adding support to retrieve TCI set in hardware. Read existing
value and only updated the PVID fields, leaving others unchanged.
Signed-off-by: Razvan Stefanescu <razvan.stefanescu@nxp.com>
---
Changelog
v2: improve patch description
v3: use the updated MC command stuct name
drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 13 +++++++++
drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 42 ++++++++++++++++++++++++++++++
drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 6 +++++
drivers/staging/fsl-dpaa2/ethsw/ethsw.c | 37 +++++++++++++-------------
4 files changed, 79 insertions(+), 19 deletions(-)
diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
index 1c203e6..da744f2 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
+++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
@@ -49,6 +49,8 @@
#define DPSW_CMDID_IF_SET_FLOODING DPSW_CMD_ID(0x047)
#define DPSW_CMDID_IF_SET_BROADCAST DPSW_CMD_ID(0x048)
+#define DPSW_CMDID_IF_GET_TCI DPSW_CMD_ID(0x04A)
+
#define DPSW_CMDID_IF_SET_LINK_CFG DPSW_CMD_ID(0x04C)
#define DPSW_CMDID_VLAN_ADD DPSW_CMD_ID(0x060)
@@ -206,6 +208,17 @@ struct dpsw_cmd_if_set_tci {
__le16 conf;
};
+struct dpsw_cmd_if_get_tci {
+ __le16 if_id;
+};
+
+struct dpsw_rsp_if_get_tci {
+ __le16 pad;
+ __le16 vlan_id;
+ u8 dei;
+ u8 pcp;
+};
+
#define DPSW_STATE_SHIFT 0
#define DPSW_STATE_SIZE 4
diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c
index 9b9bc60..cabed77 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c
@@ -529,6 +529,48 @@ int dpsw_if_set_tci(struct fsl_mc_io *mc_io,
}
/**
+ * dpsw_if_get_tci() - Get default VLAN Tag Control Information (TCI)
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token: Token of DPSW object
+ * @if_id: Interface Identifier
+ * @cfg: Tag Control Information Configuration
+ *
+ * Return: Completion status. '0' on Success; Error code otherwise.
+ */
+int dpsw_if_get_tci(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u16 if_id,
+ struct dpsw_tci_cfg *cfg)
+{
+ struct fsl_mc_command cmd = { 0 };
+ struct dpsw_cmd_if_get_tci *cmd_params;
+ struct dpsw_rsp_if_get_tci *rsp_params;
+ int err;
+
+ /* prepare command */
+ cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_TCI,
+ cmd_flags,
+ token);
+ cmd_params = (struct dpsw_cmd_if_get_tci *)cmd.params;
+ cmd_params->if_id = cpu_to_le16(if_id);
+
+ /* send command to mc*/
+ err = mc_send_command(mc_io, &cmd);
+ if (err)
+ return err;
+
+ /* retrieve response parameters */
+ rsp_params = (struct dpsw_rsp_if_get_tci *)cmd.params;
+ cfg->pcp = rsp_params->pcp;
+ cfg->dei = rsp_params->dei;
+ cfg->vlan_id = le16_to_cpu(rsp_params->vlan_id);
+
+ return 0;
+}
+
+/**
* dpsw_if_set_stp() - Function sets Spanning Tree Protocol (STP) state.
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
index 3335add..82f80c40 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
+++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
@@ -306,6 +306,12 @@ int dpsw_if_set_tci(struct fsl_mc_io *mc_io,
u16 if_id,
const struct dpsw_tci_cfg *cfg);
+int dpsw_if_get_tci(struct fsl_mc_io *mc_io,
+ u32 cmd_flags,
+ u16 token,
+ u16 if_id,
+ struct dpsw_tci_cfg *cfg);
+
/**
* enum dpsw_stp_state - Spanning Tree Protocol (STP) states
* @DPSW_STP_STATE_BLOCKING: Blocking state
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index c723a04..ab81a6c 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -50,14 +50,23 @@ static int ethsw_add_vlan(struct ethsw_core *ethsw, u16 vid)
return 0;
}
-static int ethsw_port_set_tci(struct ethsw_port_priv *port_priv,
- struct dpsw_tci_cfg *tci_cfg)
+static int ethsw_port_set_pvid(struct ethsw_port_priv *port_priv, u16 pvid)
{
struct ethsw_core *ethsw = port_priv->ethsw_data;
struct net_device *netdev = port_priv->netdev;
+ struct dpsw_tci_cfg tci_cfg = { 0 };
bool is_oper;
int err, ret;
+ err = dpsw_if_get_tci(ethsw->mc_io, 0, ethsw->dpsw_handle,
+ port_priv->idx, &tci_cfg);
+ if (err) {
+ netdev_err(netdev, "dpsw_if_get_tci err %d\n", err);
+ return err;
+ }
+
+ tci_cfg.vlan_id = pvid;
+
/* Interface needs to be down to change PVID */
is_oper = netif_oper_up(netdev);
if (is_oper) {
@@ -71,17 +80,16 @@ static int ethsw_port_set_tci(struct ethsw_port_priv *port_priv,
}
err = dpsw_if_set_tci(ethsw->mc_io, 0, ethsw->dpsw_handle,
- port_priv->idx, tci_cfg);
+ port_priv->idx, &tci_cfg);
if (err) {
netdev_err(netdev, "dpsw_if_set_tci err %d\n", err);
goto set_tci_error;
}
/* Delete previous PVID info and mark the new one */
- if (port_priv->pvid)
- port_priv->vlans[port_priv->pvid] &= ~ETHSW_VLAN_PVID;
- port_priv->vlans[tci_cfg->vlan_id] |= ETHSW_VLAN_PVID;
- port_priv->pvid = tci_cfg->vlan_id;
+ port_priv->vlans[port_priv->pvid] &= ~ETHSW_VLAN_PVID;
+ port_priv->vlans[pvid] |= ETHSW_VLAN_PVID;
+ port_priv->pvid = pvid;
set_tci_error:
if (is_oper) {
@@ -133,13 +141,7 @@ static int ethsw_port_add_vlan(struct ethsw_port_priv *port_priv,
}
if (flags & BRIDGE_VLAN_INFO_PVID) {
- struct dpsw_tci_cfg tci_cfg = {
- .pcp = 0,
- .dei = 0,
- .vlan_id = vid,
- };
-
- err = ethsw_port_set_tci(port_priv, &tci_cfg);
+ err = ethsw_port_set_pvid(port_priv, vid);
if (err)
return err;
}
@@ -819,9 +821,7 @@ static int ethsw_port_del_vlan(struct ethsw_port_priv *port_priv, u16 vid)
return -ENOENT;
if (port_priv->vlans[vid] & ETHSW_VLAN_PVID) {
- struct dpsw_tci_cfg tci_cfg = { 0 };
-
- err = ethsw_port_set_tci(port_priv, &tci_cfg);
+ err = ethsw_port_set_pvid(port_priv, 0);
if (err)
return err;
}
@@ -1254,7 +1254,6 @@ static int ethsw_port_init(struct ethsw_port_priv *port_priv, u16 port)
const char def_mcast[ETH_ALEN] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x01};
struct net_device *netdev = port_priv->netdev;
struct ethsw_core *ethsw = port_priv->ethsw_data;
- struct dpsw_tci_cfg tci_cfg = {0};
struct dpsw_vlan_if_cfg vcfg;
int err;
@@ -1272,7 +1271,7 @@ static int ethsw_port_init(struct ethsw_port_priv *port_priv, u16 port)
return err;
}
- err = ethsw_port_set_tci(port_priv, &tci_cfg);
+ err = ethsw_port_set_pvid(port_priv, 0);
if (err)
return err;
--
1.9.1
^ permalink raw reply related
* Re: [PATCH] sfp: allow cotsworks modules
From: Russell King - ARM Linux @ 2018-03-28 10:41 UTC (permalink / raw)
To: Joe Perches; +Cc: Andrew Lunn, Florian Fainelli, netdev
In-Reply-To: <1522233237.12357.96.camel@perches.com>
On Wed, Mar 28, 2018 at 03:33:57AM -0700, Joe Perches wrote:
> On Wed, 2018-03-28 at 11:18 +0100, Russell King wrote:
> > Cotsworks modules fail the checksums - it appears that Cotsworks
> > reprograms the EEPROM at the end of production with the final product
> > information (serial, date code, and exact part number for module
> > options) and fails to update the checksum.
>
> trivia:
>
> > diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
> []
> > @@ -574,23 +575,43 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
> []
> > + if (cotsworks) {
> > + dev_warn(sfp->dev,
> > + "EEPROM base structure checksum failure (0x%02x != 0x%02x)\n",
> > + check, id.base.cc_base);
> > + } else {
> > + dev_err(sfp->dev,
> > + "EEPROM base structure checksum failure: 0x%02x != 0x%02x\n",
>
> It'd be better to move this above the if and
> use only a single format string instead of
> using 2 slightly different formats.
No. I think you've missed the fact that one is a _warning_ the other is
an _error_ and they are emitted at the appropriate severity. It's not
just that the format strings are slightly different.
>
> > + check, id.base.cc_base);
> > + print_hex_dump(KERN_ERR, "sfp EE: ", DUMP_PREFIX_OFFSET,
> > + 16, 1, &id, sizeof(id), true);
> > + return -EINVAL;
> > + }
> > }
> >
> > check = sfp_check(&id.ext, sizeof(id.ext) - 1);
> > if (check != id.ext.cc_ext) {
> > - dev_err(sfp->dev,
> > - "EEPROM extended structure checksum failure: 0x%02x\n",
> > - check);
> > - memset(&id.ext, 0, sizeof(id.ext));
> > + if (cotsworks) {
> > + dev_warn(sfp->dev,
> > + "EEPROM extended structure checksum failure (0x%02x != 0x%02x)\n",
> > + check, id.ext.cc_ext);
> > + } else {
> > + dev_err(sfp->dev,
> > + "EEPROM extended structure checksum failure: 0x%02x != 0x%02x\n",
> > + check, id.ext.cc_ext);
>
>
> here too
Same applies.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
^ permalink raw reply
* Re: A cry for help, please don't ignore!
From: Sandra Y @ 2018-03-28 10:40 UTC (permalink / raw)
Good Day,
Forgive my indignation if this message comes to you as a surprise and may offend your personality for contacting you without your prior consent and writing through this channel.
I came across your name and contact on the course of my personal searching when i was searching for a foreign reliable partner. I was assured of your capability and reliability after going true your profile.
I'm (Miss. Sandra) from Benghazi libya, My father of blessed memory by name late General Abdel Fattah Younes who was shot death by Islamist-linked militia within the anti-Gaddafi forces on 28th July, 2011 and after two days later my mother with my two brothers was killed one early morning by the rebels as result of civil war that is going on in my country Libya, then after the burial of my parents, my uncles conspired and sold my father's properties and left nothing for me. On a faithful morning, I opened my father's briefcase and discover a document which he has deposited ($6.250M USD) in a bank in a Turkish Bank which has a small branch in Canada with my name as the legitimate/next of kin. Meanwhile i have located the bank,and have also discussed the possiblity of transfering the fund. M
y father left a clause to the bank that i must introduce a trusted foreign partner who would be my trustee to help me invest this fund; hence the need for your assistance,
i request that you be my trustee and assist me in this process.
You will also be responsible for the investment and management of the fund for me and also you will help me get a good school where i will further my education.
I agreed to give you 40% of the $6.250M once the transfer is done. this is my true life story, I will be glad to receive your respond soonest for more details to enable us start and champion the transfer less than 14 banking days as i was informed by the bank manager.
Thanks for giving me your attention,
Yours sincerely,
Miss. Sandra Younes
^ permalink raw reply
* Re: Aw: Re: RFC on writel and writel_relaxed
From: Benjamin Herrenschmidt @ 2018-03-28 10:20 UTC (permalink / raw)
To: Lino Sanfilippo
Cc: Will Deacon, Linus Torvalds, Alexander Duyck, Sinan Kaya,
Arnd Bergmann, Jason Gunthorpe, David Laight, Oliver,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
linux-rdma@vger.kernel.org, Paul E. McKenney,
netdev@vger.kernel.org
In-Reply-To: <trinity-2ee224b5-cbac-415e-9f8c-305e802b5369-1522232002354@3c-app-gmx-bs61>
On Wed, 2018-03-28 at 12:13 +0200, Lino Sanfilippo wrote:
> Hi,
>
>
> >
> > Yeah so that other trick I'm talking about is also used for timing
> > accuracy.
> >
> > For example, let's say I have a device with a reset bit and the spec
> > says the reset bit needs to be set for at least 10us.
> >
> > This is wrong:
> >
> > writel(1, RESET_REG);
> > usleep(10);
> > writel(0, RESET_REG);
> >
> > Because of write posting, the first write might arrive to the device
> > right before the second one.
> >
>
> Does not write posting only concern PCI? This seems to be a different topic. Furthermore
> write posting should not include write reordering...
Nobody's talking about re-ordering and no, write posting is rather
common practice on a whole lot of different busses, not just PCI(e).
Cheers,
Ben.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox