diff options
author | Yi Zou <yi.zou@intel.com> | 2011-02-01 02:22:16 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-03-07 21:04:35 -0500 |
commit | 68a683cf6a5ff09faa366fc1fcf967add0211fe8 (patch) | |
tree | ce031702ba79d9039bb4f0843a8f056885ba94e4 | |
parent | 4ea09c9caaebc98d06a39c435d4359912cfbb5e2 (diff) |
ixgbe: add support to FCoE DDP in target mode
Add support to the ndo_fcoe_ddp_target() to allow the Intel 82599 device to
also provide DDP offload capability when the upper FCoE protocol stack is
operating as a target.
Signed-off-by: Yi Zou <yi.zou@intel.com>
Signed-off-by: Kiran Patil <kiran.patil@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r-- | drivers/net/ixgbe/ixgbe.h | 2 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_fcoe.c | 86 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_fcoe.h | 4 | ||||
-rw-r--r-- | drivers/net/ixgbe/ixgbe_main.c | 1 |
4 files changed, 81 insertions, 12 deletions
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index b60b81bc2b15..1e546fc127d0 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h | |||
@@ -552,6 +552,8 @@ extern int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, | |||
552 | struct sk_buff *skb); | 552 | struct sk_buff *skb); |
553 | extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, | 553 | extern int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, |
554 | struct scatterlist *sgl, unsigned int sgc); | 554 | struct scatterlist *sgl, unsigned int sgc); |
555 | extern int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid, | ||
556 | struct scatterlist *sgl, unsigned int sgc); | ||
555 | extern int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid); | 557 | extern int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid); |
556 | extern int ixgbe_fcoe_enable(struct net_device *netdev); | 558 | extern int ixgbe_fcoe_enable(struct net_device *netdev); |
557 | extern int ixgbe_fcoe_disable(struct net_device *netdev); | 559 | extern int ixgbe_fcoe_disable(struct net_device *netdev); |
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.c b/drivers/net/ixgbe/ixgbe_fcoe.c index 27203c87ea14..00af15a9cdc6 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.c +++ b/drivers/net/ixgbe/ixgbe_fcoe.c | |||
@@ -135,22 +135,19 @@ out_ddp_put: | |||
135 | return len; | 135 | return len; |
136 | } | 136 | } |
137 | 137 | ||
138 | |||
138 | /** | 139 | /** |
139 | * ixgbe_fcoe_ddp_get - called to set up ddp context | 140 | * ixgbe_fcoe_ddp_setup - called to set up ddp context |
140 | * @netdev: the corresponding net_device | 141 | * @netdev: the corresponding net_device |
141 | * @xid: the exchange id requesting ddp | 142 | * @xid: the exchange id requesting ddp |
142 | * @sgl: the scatter-gather list for this request | 143 | * @sgl: the scatter-gather list for this request |
143 | * @sgc: the number of scatter-gather items | 144 | * @sgc: the number of scatter-gather items |
144 | * | 145 | * |
145 | * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup | ||
146 | * and is expected to be called from ULD, e.g., FCP layer of libfc | ||
147 | * to set up ddp for the corresponding xid of the given sglist for | ||
148 | * the corresponding I/O. | ||
149 | * | ||
150 | * Returns : 1 for success and 0 for no ddp | 146 | * Returns : 1 for success and 0 for no ddp |
151 | */ | 147 | */ |
152 | int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, | 148 | static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid, |
153 | struct scatterlist *sgl, unsigned int sgc) | 149 | struct scatterlist *sgl, unsigned int sgc, |
150 | int target_mode) | ||
154 | { | 151 | { |
155 | struct ixgbe_adapter *adapter; | 152 | struct ixgbe_adapter *adapter; |
156 | struct ixgbe_hw *hw; | 153 | struct ixgbe_hw *hw; |
@@ -164,7 +161,7 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, | |||
164 | unsigned int lastsize; | 161 | unsigned int lastsize; |
165 | unsigned int thisoff = 0; | 162 | unsigned int thisoff = 0; |
166 | unsigned int thislen = 0; | 163 | unsigned int thislen = 0; |
167 | u32 fcbuff, fcdmarw, fcfltrw; | 164 | u32 fcbuff, fcdmarw, fcfltrw, fcrxctl; |
168 | dma_addr_t addr = 0; | 165 | dma_addr_t addr = 0; |
169 | 166 | ||
170 | if (!netdev || !sgl) | 167 | if (!netdev || !sgl) |
@@ -275,6 +272,9 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, | |||
275 | fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT); | 272 | fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT); |
276 | fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT); | 273 | fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT); |
277 | fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT); | 274 | fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT); |
275 | /* Set WRCONTX bit to allow DDP for target */ | ||
276 | if (target_mode) | ||
277 | fcbuff |= (IXGBE_FCBUFF_WRCONTX); | ||
278 | fcbuff |= (IXGBE_FCBUFF_VALID); | 278 | fcbuff |= (IXGBE_FCBUFF_VALID); |
279 | 279 | ||
280 | fcdmarw = xid; | 280 | fcdmarw = xid; |
@@ -287,6 +287,16 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, | |||
287 | /* program DMA context */ | 287 | /* program DMA context */ |
288 | hw = &adapter->hw; | 288 | hw = &adapter->hw; |
289 | spin_lock_bh(&fcoe->lock); | 289 | spin_lock_bh(&fcoe->lock); |
290 | |||
291 | /* turn on last frame indication for target mode as FCP_RSPtarget is | ||
292 | * supposed to send FCP_RSP when it is done. */ | ||
293 | if (target_mode && !test_bit(__IXGBE_FCOE_TARGET, &fcoe->mode)) { | ||
294 | set_bit(__IXGBE_FCOE_TARGET, &fcoe->mode); | ||
295 | fcrxctl = IXGBE_READ_REG(hw, IXGBE_FCRXCTRL); | ||
296 | fcrxctl |= IXGBE_FCRXCTRL_LASTSEQH; | ||
297 | IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL, fcrxctl); | ||
298 | } | ||
299 | |||
290 | IXGBE_WRITE_REG(hw, IXGBE_FCPTRL, ddp->udp & DMA_BIT_MASK(32)); | 300 | IXGBE_WRITE_REG(hw, IXGBE_FCPTRL, ddp->udp & DMA_BIT_MASK(32)); |
291 | IXGBE_WRITE_REG(hw, IXGBE_FCPTRH, (u64)ddp->udp >> 32); | 301 | IXGBE_WRITE_REG(hw, IXGBE_FCPTRH, (u64)ddp->udp >> 32); |
292 | IXGBE_WRITE_REG(hw, IXGBE_FCBUFF, fcbuff); | 302 | IXGBE_WRITE_REG(hw, IXGBE_FCBUFF, fcbuff); |
@@ -295,6 +305,7 @@ int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, | |||
295 | IXGBE_WRITE_REG(hw, IXGBE_FCPARAM, 0); | 305 | IXGBE_WRITE_REG(hw, IXGBE_FCPARAM, 0); |
296 | IXGBE_WRITE_REG(hw, IXGBE_FCFLT, IXGBE_FCFLT_VALID); | 306 | IXGBE_WRITE_REG(hw, IXGBE_FCFLT, IXGBE_FCFLT_VALID); |
297 | IXGBE_WRITE_REG(hw, IXGBE_FCFLTRW, fcfltrw); | 307 | IXGBE_WRITE_REG(hw, IXGBE_FCFLTRW, fcfltrw); |
308 | |||
298 | spin_unlock_bh(&fcoe->lock); | 309 | spin_unlock_bh(&fcoe->lock); |
299 | 310 | ||
300 | return 1; | 311 | return 1; |
@@ -309,6 +320,47 @@ out_noddp_unmap: | |||
309 | } | 320 | } |
310 | 321 | ||
311 | /** | 322 | /** |
323 | * ixgbe_fcoe_ddp_get - called to set up ddp context in initiator mode | ||
324 | * @netdev: the corresponding net_device | ||
325 | * @xid: the exchange id requesting ddp | ||
326 | * @sgl: the scatter-gather list for this request | ||
327 | * @sgc: the number of scatter-gather items | ||
328 | * | ||
329 | * This is the implementation of net_device_ops.ndo_fcoe_ddp_setup | ||
330 | * and is expected to be called from ULD, e.g., FCP layer of libfc | ||
331 | * to set up ddp for the corresponding xid of the given sglist for | ||
332 | * the corresponding I/O. | ||
333 | * | ||
334 | * Returns : 1 for success and 0 for no ddp | ||
335 | */ | ||
336 | int ixgbe_fcoe_ddp_get(struct net_device *netdev, u16 xid, | ||
337 | struct scatterlist *sgl, unsigned int sgc) | ||
338 | { | ||
339 | return ixgbe_fcoe_ddp_setup(netdev, xid, sgl, sgc, 0); | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * ixgbe_fcoe_ddp_target - called to set up ddp context in target mode | ||
344 | * @netdev: the corresponding net_device | ||
345 | * @xid: the exchange id requesting ddp | ||
346 | * @sgl: the scatter-gather list for this request | ||
347 | * @sgc: the number of scatter-gather items | ||
348 | * | ||
349 | * This is the implementation of net_device_ops.ndo_fcoe_ddp_target | ||
350 | * and is expected to be called from ULD, e.g., FCP layer of libfc | ||
351 | * to set up ddp for the corresponding xid of the given sglist for | ||
352 | * the corresponding I/O. The DDP in target mode is a write I/O request | ||
353 | * from the initiator. | ||
354 | * | ||
355 | * Returns : 1 for success and 0 for no ddp | ||
356 | */ | ||
357 | int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid, | ||
358 | struct scatterlist *sgl, unsigned int sgc) | ||
359 | { | ||
360 | return ixgbe_fcoe_ddp_setup(netdev, xid, sgl, sgc, 1); | ||
361 | } | ||
362 | |||
363 | /** | ||
312 | * ixgbe_fcoe_ddp - check ddp status and mark it done | 364 | * ixgbe_fcoe_ddp - check ddp status and mark it done |
313 | * @adapter: ixgbe adapter | 365 | * @adapter: ixgbe adapter |
314 | * @rx_desc: advanced rx descriptor | 366 | * @rx_desc: advanced rx descriptor |
@@ -331,6 +383,7 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, | |||
331 | struct ixgbe_fcoe *fcoe; | 383 | struct ixgbe_fcoe *fcoe; |
332 | struct ixgbe_fcoe_ddp *ddp; | 384 | struct ixgbe_fcoe_ddp *ddp; |
333 | struct fc_frame_header *fh; | 385 | struct fc_frame_header *fh; |
386 | struct fcoe_crc_eof *crc; | ||
334 | 387 | ||
335 | if (!ixgbe_rx_is_fcoe(rx_desc)) | 388 | if (!ixgbe_rx_is_fcoe(rx_desc)) |
336 | goto ddp_out; | 389 | goto ddp_out; |
@@ -384,7 +437,18 @@ int ixgbe_fcoe_ddp(struct ixgbe_adapter *adapter, | |||
384 | else if (ddp->len) | 437 | else if (ddp->len) |
385 | rc = ddp->len; | 438 | rc = ddp->len; |
386 | } | 439 | } |
387 | 440 | /* In target mode, check the last data frame of the sequence. | |
441 | * For DDP in target mode, data is already DDPed but the header | ||
442 | * indication of the last data frame ould allow is to tell if we | ||
443 | * got all the data and the ULP can send FCP_RSP back, as this is | ||
444 | * not a full fcoe frame, we fill the trailer here so it won't be | ||
445 | * dropped by the ULP stack. | ||
446 | */ | ||
447 | if ((fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA) && | ||
448 | (fctl & FC_FC_END_SEQ)) { | ||
449 | crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc)); | ||
450 | crc->fcoe_eof = FC_EOF_T; | ||
451 | } | ||
388 | ddp_out: | 452 | ddp_out: |
389 | return rc; | 453 | return rc; |
390 | } | 454 | } |
@@ -840,5 +904,3 @@ int ixgbe_fcoe_get_wwn(struct net_device *netdev, u64 *wwn, int type) | |||
840 | } | 904 | } |
841 | return rc; | 905 | return rc; |
842 | } | 906 | } |
843 | |||
844 | |||
diff --git a/drivers/net/ixgbe/ixgbe_fcoe.h b/drivers/net/ixgbe/ixgbe_fcoe.h index 02a00d2415d9..5a650a4ace66 100644 --- a/drivers/net/ixgbe/ixgbe_fcoe.h +++ b/drivers/net/ixgbe/ixgbe_fcoe.h | |||
@@ -52,6 +52,9 @@ | |||
52 | /* fcerr */ | 52 | /* fcerr */ |
53 | #define IXGBE_FCERR_BADCRC 0x00100000 | 53 | #define IXGBE_FCERR_BADCRC 0x00100000 |
54 | 54 | ||
55 | /* FCoE DDP for target mode */ | ||
56 | #define __IXGBE_FCOE_TARGET 1 | ||
57 | |||
55 | struct ixgbe_fcoe_ddp { | 58 | struct ixgbe_fcoe_ddp { |
56 | int len; | 59 | int len; |
57 | u32 err; | 60 | u32 err; |
@@ -66,6 +69,7 @@ struct ixgbe_fcoe { | |||
66 | u8 tc; | 69 | u8 tc; |
67 | u8 up; | 70 | u8 up; |
68 | #endif | 71 | #endif |
72 | unsigned long mode; | ||
69 | atomic_t refcnt; | 73 | atomic_t refcnt; |
70 | spinlock_t lock; | 74 | spinlock_t lock; |
71 | struct pci_pool *pool; | 75 | struct pci_pool *pool; |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 32231ffe0717..5e8c39decca1 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -7019,6 +7019,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { | |||
7019 | #endif | 7019 | #endif |
7020 | #ifdef IXGBE_FCOE | 7020 | #ifdef IXGBE_FCOE |
7021 | .ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get, | 7021 | .ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get, |
7022 | .ndo_fcoe_ddp_target = ixgbe_fcoe_ddp_target, | ||
7022 | .ndo_fcoe_ddp_done = ixgbe_fcoe_ddp_put, | 7023 | .ndo_fcoe_ddp_done = ixgbe_fcoe_ddp_put, |
7023 | .ndo_fcoe_enable = ixgbe_fcoe_enable, | 7024 | .ndo_fcoe_enable = ixgbe_fcoe_enable, |
7024 | .ndo_fcoe_disable = ixgbe_fcoe_disable, | 7025 | .ndo_fcoe_disable = ixgbe_fcoe_disable, |