diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/fcoe/fcoe.c | 5 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 20 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_frame.c | 5 |
3 files changed, 16 insertions, 14 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 28029a34289..b570f39faa3 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c | |||
@@ -1267,10 +1267,11 @@ err2: | |||
1267 | */ | 1267 | */ |
1268 | static inline int fcoe_start_io(struct sk_buff *skb) | 1268 | static inline int fcoe_start_io(struct sk_buff *skb) |
1269 | { | 1269 | { |
1270 | struct sk_buff *nskb; | ||
1270 | int rc; | 1271 | int rc; |
1271 | 1272 | ||
1272 | skb_get(skb); | 1273 | nskb = skb_clone(skb, GFP_ATOMIC); |
1273 | rc = dev_queue_xmit(skb); | 1274 | rc = dev_queue_xmit(nskb); |
1274 | if (rc != 0) | 1275 | if (rc != 0) |
1275 | return rc; | 1276 | return rc; |
1276 | kfree_skb(skb); | 1277 | kfree_skb(skb); |
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index db252e2722d..c4b58d042f6 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c | |||
@@ -530,11 +530,13 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, | |||
530 | struct scatterlist *sg; | 530 | struct scatterlist *sg; |
531 | struct fc_frame *fp = NULL; | 531 | struct fc_frame *fp = NULL; |
532 | struct fc_lport *lport = fsp->lp; | 532 | struct fc_lport *lport = fsp->lp; |
533 | struct page *page; | ||
533 | size_t remaining; | 534 | size_t remaining; |
534 | size_t t_blen; | 535 | size_t t_blen; |
535 | size_t tlen; | 536 | size_t tlen; |
536 | size_t sg_bytes; | 537 | size_t sg_bytes; |
537 | size_t frame_offset, fh_parm_offset; | 538 | size_t frame_offset, fh_parm_offset; |
539 | size_t off; | ||
538 | int error; | 540 | int error; |
539 | void *data = NULL; | 541 | void *data = NULL; |
540 | void *page_addr; | 542 | void *page_addr; |
@@ -605,28 +607,26 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, | |||
605 | fh_parm_offset = frame_offset; | 607 | fh_parm_offset = frame_offset; |
606 | fr_max_payload(fp) = fsp->max_payload; | 608 | fr_max_payload(fp) = fsp->max_payload; |
607 | } | 609 | } |
610 | |||
611 | off = offset + sg->offset; | ||
608 | sg_bytes = min(tlen, sg->length - offset); | 612 | sg_bytes = min(tlen, sg->length - offset); |
613 | sg_bytes = min(sg_bytes, | ||
614 | (size_t) (PAGE_SIZE - (off & ~PAGE_MASK))); | ||
615 | page = sg_page(sg) + (off >> PAGE_SHIFT); | ||
609 | if (using_sg) { | 616 | if (using_sg) { |
610 | get_page(sg_page(sg)); | 617 | get_page(page); |
611 | skb_fill_page_desc(fp_skb(fp), | 618 | skb_fill_page_desc(fp_skb(fp), |
612 | skb_shinfo(fp_skb(fp))->nr_frags, | 619 | skb_shinfo(fp_skb(fp))->nr_frags, |
613 | sg_page(sg), sg->offset + offset, | 620 | page, off & ~PAGE_MASK, sg_bytes); |
614 | sg_bytes); | ||
615 | fp_skb(fp)->data_len += sg_bytes; | 621 | fp_skb(fp)->data_len += sg_bytes; |
616 | fr_len(fp) += sg_bytes; | 622 | fr_len(fp) += sg_bytes; |
617 | fp_skb(fp)->truesize += PAGE_SIZE; | 623 | fp_skb(fp)->truesize += PAGE_SIZE; |
618 | } else { | 624 | } else { |
619 | size_t off = offset + sg->offset; | ||
620 | |||
621 | /* | 625 | /* |
622 | * The scatterlist item may be bigger than PAGE_SIZE, | 626 | * The scatterlist item may be bigger than PAGE_SIZE, |
623 | * but we must not cross pages inside the kmap. | 627 | * but we must not cross pages inside the kmap. |
624 | */ | 628 | */ |
625 | sg_bytes = min(sg_bytes, (size_t) (PAGE_SIZE - | 629 | page_addr = kmap_atomic(page, KM_SOFTIRQ0); |
626 | (off & ~PAGE_MASK))); | ||
627 | page_addr = kmap_atomic(sg_page(sg) + | ||
628 | (off >> PAGE_SHIFT), | ||
629 | KM_SOFTIRQ0); | ||
630 | memcpy(data, (char *)page_addr + (off & ~PAGE_MASK), | 630 | memcpy(data, (char *)page_addr + (off & ~PAGE_MASK), |
631 | sg_bytes); | 631 | sg_bytes); |
632 | kunmap_atomic(page_addr, KM_SOFTIRQ0); | 632 | kunmap_atomic(page_addr, KM_SOFTIRQ0); |
diff --git a/drivers/scsi/libfc/fc_frame.c b/drivers/scsi/libfc/fc_frame.c index 79c956501bd..6da01c61696 100644 --- a/drivers/scsi/libfc/fc_frame.c +++ b/drivers/scsi/libfc/fc_frame.c | |||
@@ -58,12 +58,13 @@ struct fc_frame *_fc_frame_alloc(size_t len) | |||
58 | 58 | ||
59 | WARN_ON((len % sizeof(u32)) != 0); | 59 | WARN_ON((len % sizeof(u32)) != 0); |
60 | len += sizeof(struct fc_frame_header); | 60 | len += sizeof(struct fc_frame_header); |
61 | skb = dev_alloc_skb(len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM); | 61 | skb = alloc_skb_fclone(len + FC_FRAME_HEADROOM + FC_FRAME_TAILROOM + |
62 | NET_SKB_PAD, GFP_ATOMIC); | ||
62 | if (!skb) | 63 | if (!skb) |
63 | return NULL; | 64 | return NULL; |
65 | skb_reserve(skb, NET_SKB_PAD + FC_FRAME_HEADROOM); | ||
64 | fp = (struct fc_frame *) skb; | 66 | fp = (struct fc_frame *) skb; |
65 | fc_frame_init(fp); | 67 | fc_frame_init(fp); |
66 | skb_reserve(skb, FC_FRAME_HEADROOM); | ||
67 | skb_put(skb, len); | 68 | skb_put(skb, len); |
68 | return fp; | 69 | return fp; |
69 | } | 70 | } |