aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/brocade
diff options
context:
space:
mode:
authorKrishna Gudipati <kgudipat@brocade.com>2011-12-22 08:29:45 -0500
committerDavid S. Miller <davem@davemloft.net>2011-12-23 16:50:58 -0500
commit72a9730b3f556e18912f3e1b494a7aee7ae3dd91 (patch)
tree1b589cb530e6cf5145a29c3423c176408c667033 /drivers/net/ethernet/brocade
parent6fc0d0f2e3bcbb4bfbc22a89c996e5905da4cc43 (diff)
bna: Added flash sub-module and ethtool eeprom entry points.
Change details: - The patch adds flash sub-module to the bna driver. - Added ethtool set_eeprom() and get_eeprom() entry points to support flash partition read/write operations. Signed-off-by: Krishna Gudipati <kgudipat@brocade.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/brocade')
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_defs.h98
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.c372
-rw-r--r--drivers/net/ethernet/brocade/bna/bfa_ioc.h48
-rw-r--r--drivers/net/ethernet/brocade/bna/bfi.h95
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_enet.c8
-rw-r--r--drivers/net/ethernet/brocade/bna/bna_types.h1
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c37
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.h9
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad_ethtool.c142
9 files changed, 771 insertions, 39 deletions
diff --git a/drivers/net/ethernet/brocade/bna/bfa_defs.h b/drivers/net/ethernet/brocade/bna/bfa_defs.h
index 2f12d68021d5..871c6309334c 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_defs.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_defs.h
@@ -219,41 +219,39 @@ enum {
219 * All numerical fields are in big-endian format. 219 * All numerical fields are in big-endian format.
220 */ 220 */
221struct bfa_mfg_block { 221struct bfa_mfg_block {
222 u8 version; /*!< manufacturing block version */ 222 u8 version; /* manufacturing block version */
223 u8 mfg_sig[3]; /*!< characters 'M', 'F', 'G' */ 223 u8 mfg_sig[3]; /* characters 'M', 'F', 'G' */
224 u16 mfgsize; /*!< mfg block size */ 224 u16 mfgsize; /* mfg block size */
225 u16 u16_chksum; /*!< old u16 checksum */ 225 u16 u16_chksum; /* old u16 checksum */
226 char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)]; 226 char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)];
227 char brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)]; 227 char brcd_partnum[STRSZ(BFA_MFG_PARTNUM_SIZE)];
228 u8 mfg_day; /*!< manufacturing day */ 228 u8 mfg_day; /* manufacturing day */
229 u8 mfg_month; /*!< manufacturing month */ 229 u8 mfg_month; /* manufacturing month */
230 u16 mfg_year; /*!< manufacturing year */ 230 u16 mfg_year; /* manufacturing year */
231 u64 mfg_wwn; /*!< wwn base for this adapter */ 231 u64 mfg_wwn; /* wwn base for this adapter */
232 u8 num_wwn; /*!< number of wwns assigned */ 232 u8 num_wwn; /* number of wwns assigned */
233 u8 mfg_speeds; /*!< speeds allowed for this adapter */ 233 u8 mfg_speeds; /* speeds allowed for this adapter */
234 u8 rsv[2]; 234 u8 rsv[2];
235 char supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)]; 235 char supplier_id[STRSZ(BFA_MFG_SUPPLIER_ID_SIZE)];
236 char supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)]; 236 char supplier_partnum[STRSZ(BFA_MFG_SUPPLIER_PARTNUM_SIZE)];
237 char 237 char supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)];
238 supplier_serialnum[STRSZ(BFA_MFG_SUPPLIER_SERIALNUM_SIZE)]; 238 char supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)];
239 char 239 mac_t mfg_mac; /* base mac address */
240 supplier_revision[STRSZ(BFA_MFG_SUPPLIER_REVISION_SIZE)]; 240 u8 num_mac; /* number of mac addresses */
241 mac_t mfg_mac; /*!< mac address */ 241 u8 rsv2;
242 u8 num_mac; /*!< number of mac addresses */ 242 u32 card_type; /* card type */
243 u8 rsv2; 243 char cap_nic; /* capability nic */
244 u32 card_type; /*!< card type */ 244 char cap_cna; /* capability cna */
245 char cap_nic; /*!< capability nic */ 245 char cap_hba; /* capability hba */
246 char cap_cna; /*!< capability cna */ 246 char cap_fc16g; /* capability fc 16g */
247 char cap_hba; /*!< capability hba */ 247 char cap_sriov; /* capability sriov */
248 char cap_fc16g; /*!< capability fc 16g */ 248 char cap_mezz; /* capability mezz */
249 char cap_sriov; /*!< capability sriov */ 249 u8 rsv3;
250 char cap_mezz; /*!< capability mezz */ 250 u8 mfg_nports; /* number of ports */
251 u8 rsv3; 251 char media[8]; /* xfi/xaui */
252 u8 mfg_nports; /*!< number of ports */ 252 char initial_mode[8]; /* initial mode: hba/cna/nic */
253 char media[8]; /*!< xfi/xaui */ 253 u8 rsv4[84];
254 char initial_mode[8];/*!< initial mode: hba/cna/nic */ 254 u8 md5_chksum[BFA_MFG_CHKSUM_SIZE]; /* md5 checksum */
255 u8 rsv4[84];
256 u8 md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */
257}; 255};
258 256
259#pragma pack() 257#pragma pack()
@@ -293,4 +291,34 @@ enum bfa_mode {
293 BFA_MODE_NIC = 3 291 BFA_MODE_NIC = 3
294}; 292};
295 293
294/*
295 * Flash module specific
296 */
297#define BFA_FLASH_PART_ENTRY_SIZE 32 /* partition entry size */
298#define BFA_FLASH_PART_MAX 32 /* maximal # of partitions */
299#define BFA_TOTAL_FLASH_SIZE 0x400000
300#define BFA_FLASH_PART_MFG 7
301
302/*
303 * flash partition attributes
304 */
305struct bfa_flash_part_attr {
306 u32 part_type; /* partition type */
307 u32 part_instance; /* partition instance */
308 u32 part_off; /* partition offset */
309 u32 part_size; /* partition size */
310 u32 part_len; /* partition content length */
311 u32 part_status; /* partition status */
312 char rsv[BFA_FLASH_PART_ENTRY_SIZE - 24];
313};
314
315/*
316 * flash attributes
317 */
318struct bfa_flash_attr {
319 u32 status; /* flash overall status */
320 u32 npart; /* num of partitions */
321 struct bfa_flash_part_attr part[BFA_FLASH_PART_MAX];
322};
323
296#endif /* __BFA_DEFS_H__ */ 324#endif /* __BFA_DEFS_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
index b0307a00a109..1d130445efbc 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c
@@ -2172,6 +2172,15 @@ bfa_nw_ioc_is_disabled(struct bfa_ioc *ioc)
2172} 2172}
2173 2173
2174/** 2174/**
2175 * return true if IOC is operational
2176 */
2177bool
2178bfa_nw_ioc_is_operational(struct bfa_ioc *ioc)
2179{
2180 return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op);
2181}
2182
2183/**
2175 * Add to IOC heartbeat failure notification queue. To be used by common 2184 * Add to IOC heartbeat failure notification queue. To be used by common
2176 * modules such as cee, port, diag. 2185 * modules such as cee, port, diag.
2177 */ 2186 */
@@ -2471,3 +2480,366 @@ bfa_ioc_poll_fwinit(struct bfa_ioc *ioc)
2471 msecs_to_jiffies(BFA_IOC_POLL_TOV)); 2480 msecs_to_jiffies(BFA_IOC_POLL_TOV));
2472 } 2481 }
2473} 2482}
2483
2484/*
2485 * Flash module specific
2486 */
2487
2488/*
2489 * FLASH DMA buffer should be big enough to hold both MFG block and
2490 * asic block(64k) at the same time and also should be 2k aligned to
2491 * avoid write segement to cross sector boundary.
2492 */
2493#define BFA_FLASH_SEG_SZ 2048
2494#define BFA_FLASH_DMA_BUF_SZ \
2495 roundup(0x010000 + sizeof(struct bfa_mfg_block), BFA_FLASH_SEG_SZ)
2496
2497static void
2498bfa_flash_cb(struct bfa_flash *flash)
2499{
2500 flash->op_busy = 0;
2501 if (flash->cbfn)
2502 flash->cbfn(flash->cbarg, flash->status);
2503}
2504
2505static void
2506bfa_flash_notify(void *cbarg, enum bfa_ioc_event event)
2507{
2508 struct bfa_flash *flash = cbarg;
2509
2510 switch (event) {
2511 case BFA_IOC_E_DISABLED:
2512 case BFA_IOC_E_FAILED:
2513 if (flash->op_busy) {
2514 flash->status = BFA_STATUS_IOC_FAILURE;
2515 flash->cbfn(flash->cbarg, flash->status);
2516 flash->op_busy = 0;
2517 }
2518 break;
2519 default:
2520 break;
2521 }
2522}
2523
2524/*
2525 * Send flash write request.
2526 *
2527 * @param[in] cbarg - callback argument
2528 */
2529static void
2530bfa_flash_write_send(struct bfa_flash *flash)
2531{
2532 struct bfi_flash_write_req *msg =
2533 (struct bfi_flash_write_req *) flash->mb.msg;
2534 u32 len;
2535
2536 msg->type = be32_to_cpu(flash->type);
2537 msg->instance = flash->instance;
2538 msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
2539 len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
2540 flash->residue : BFA_FLASH_DMA_BUF_SZ;
2541 msg->length = be32_to_cpu(len);
2542
2543 /* indicate if it's the last msg of the whole write operation */
2544 msg->last = (len == flash->residue) ? 1 : 0;
2545
2546 bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_WRITE_REQ,
2547 bfa_ioc_portid(flash->ioc));
2548 bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
2549 memcpy(flash->dbuf_kva, flash->ubuf + flash->offset, len);
2550 bfa_nw_ioc_mbox_queue(flash->ioc, &flash->mb, NULL, NULL);
2551
2552 flash->residue -= len;
2553 flash->offset += len;
2554}
2555
2556/*
2557 * Send flash read request.
2558 *
2559 * @param[in] cbarg - callback argument
2560 */
2561static void
2562bfa_flash_read_send(void *cbarg)
2563{
2564 struct bfa_flash *flash = cbarg;
2565 struct bfi_flash_read_req *msg =
2566 (struct bfi_flash_read_req *) flash->mb.msg;
2567 u32 len;
2568
2569 msg->type = be32_to_cpu(flash->type);
2570 msg->instance = flash->instance;
2571 msg->offset = be32_to_cpu(flash->addr_off + flash->offset);
2572 len = (flash->residue < BFA_FLASH_DMA_BUF_SZ) ?
2573 flash->residue : BFA_FLASH_DMA_BUF_SZ;
2574 msg->length = be32_to_cpu(len);
2575 bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_READ_REQ,
2576 bfa_ioc_portid(flash->ioc));
2577 bfa_alen_set(&msg->alen, len, flash->dbuf_pa);
2578 bfa_nw_ioc_mbox_queue(flash->ioc, &flash->mb, NULL, NULL);
2579}
2580
2581/*
2582 * Process flash response messages upon receiving interrupts.
2583 *
2584 * @param[in] flasharg - flash structure
2585 * @param[in] msg - message structure
2586 */
2587static void
2588bfa_flash_intr(void *flasharg, struct bfi_mbmsg *msg)
2589{
2590 struct bfa_flash *flash = flasharg;
2591 u32 status;
2592
2593 union {
2594 struct bfi_flash_query_rsp *query;
2595 struct bfi_flash_write_rsp *write;
2596 struct bfi_flash_read_rsp *read;
2597 struct bfi_mbmsg *msg;
2598 } m;
2599
2600 m.msg = msg;
2601
2602 /* receiving response after ioc failure */
2603 if (!flash->op_busy && msg->mh.msg_id != BFI_FLASH_I2H_EVENT)
2604 return;
2605
2606 switch (msg->mh.msg_id) {
2607 case BFI_FLASH_I2H_QUERY_RSP:
2608 status = be32_to_cpu(m.query->status);
2609 if (status == BFA_STATUS_OK) {
2610 u32 i;
2611 struct bfa_flash_attr *attr, *f;
2612
2613 attr = (struct bfa_flash_attr *) flash->ubuf;
2614 f = (struct bfa_flash_attr *) flash->dbuf_kva;
2615 attr->status = be32_to_cpu(f->status);
2616 attr->npart = be32_to_cpu(f->npart);
2617 for (i = 0; i < attr->npart; i++) {
2618 attr->part[i].part_type =
2619 be32_to_cpu(f->part[i].part_type);
2620 attr->part[i].part_instance =
2621 be32_to_cpu(f->part[i].part_instance);
2622 attr->part[i].part_off =
2623 be32_to_cpu(f->part[i].part_off);
2624 attr->part[i].part_size =
2625 be32_to_cpu(f->part[i].part_size);
2626 attr->part[i].part_len =
2627 be32_to_cpu(f->part[i].part_len);
2628 attr->part[i].part_status =
2629 be32_to_cpu(f->part[i].part_status);
2630 }
2631 }
2632 flash->status = status;
2633 bfa_flash_cb(flash);
2634 break;
2635 case BFI_FLASH_I2H_WRITE_RSP:
2636 status = be32_to_cpu(m.write->status);
2637 if (status != BFA_STATUS_OK || flash->residue == 0) {
2638 flash->status = status;
2639 bfa_flash_cb(flash);
2640 } else
2641 bfa_flash_write_send(flash);
2642 break;
2643 case BFI_FLASH_I2H_READ_RSP:
2644 status = be32_to_cpu(m.read->status);
2645 if (status != BFA_STATUS_OK) {
2646 flash->status = status;
2647 bfa_flash_cb(flash);
2648 } else {
2649 u32 len = be32_to_cpu(m.read->length);
2650 memcpy(flash->ubuf + flash->offset,
2651 flash->dbuf_kva, len);
2652 flash->residue -= len;
2653 flash->offset += len;
2654 if (flash->residue == 0) {
2655 flash->status = status;
2656 bfa_flash_cb(flash);
2657 } else
2658 bfa_flash_read_send(flash);
2659 }
2660 break;
2661 case BFI_FLASH_I2H_BOOT_VER_RSP:
2662 case BFI_FLASH_I2H_EVENT:
2663 break;
2664 default:
2665 WARN_ON(1);
2666 }
2667}
2668
2669/*
2670 * Flash memory info API.
2671 */
2672u32
2673bfa_nw_flash_meminfo(void)
2674{
2675 return roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
2676}
2677
2678/*
2679 * Flash attach API.
2680 *
2681 * @param[in] flash - flash structure
2682 * @param[in] ioc - ioc structure
2683 * @param[in] dev - device structure
2684 */
2685void
2686bfa_nw_flash_attach(struct bfa_flash *flash, struct bfa_ioc *ioc, void *dev)
2687{
2688 flash->ioc = ioc;
2689 flash->cbfn = NULL;
2690 flash->cbarg = NULL;
2691 flash->op_busy = 0;
2692
2693 bfa_nw_ioc_mbox_regisr(flash->ioc, BFI_MC_FLASH, bfa_flash_intr, flash);
2694 bfa_q_qe_init(&flash->ioc_notify);
2695 bfa_ioc_notify_init(&flash->ioc_notify, bfa_flash_notify, flash);
2696 list_add_tail(&flash->ioc_notify.qe, &flash->ioc->notify_q);
2697}
2698
2699/*
2700 * Claim memory for flash
2701 *
2702 * @param[in] flash - flash structure
2703 * @param[in] dm_kva - pointer to virtual memory address
2704 * @param[in] dm_pa - physical memory address
2705 */
2706void
2707bfa_nw_flash_memclaim(struct bfa_flash *flash, u8 *dm_kva, u64 dm_pa)
2708{
2709 flash->dbuf_kva = dm_kva;
2710 flash->dbuf_pa = dm_pa;
2711 memset(flash->dbuf_kva, 0, BFA_FLASH_DMA_BUF_SZ);
2712 dm_kva += roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
2713 dm_pa += roundup(BFA_FLASH_DMA_BUF_SZ, BFA_DMA_ALIGN_SZ);
2714}
2715
2716/*
2717 * Get flash attribute.
2718 *
2719 * @param[in] flash - flash structure
2720 * @param[in] attr - flash attribute structure
2721 * @param[in] cbfn - callback function
2722 * @param[in] cbarg - callback argument
2723 *
2724 * Return status.
2725 */
2726enum bfa_status
2727bfa_nw_flash_get_attr(struct bfa_flash *flash, struct bfa_flash_attr *attr,
2728 bfa_cb_flash cbfn, void *cbarg)
2729{
2730 struct bfi_flash_query_req *msg =
2731 (struct bfi_flash_query_req *) flash->mb.msg;
2732
2733 if (!bfa_nw_ioc_is_operational(flash->ioc))
2734 return BFA_STATUS_IOC_NON_OP;
2735
2736 if (flash->op_busy)
2737 return BFA_STATUS_DEVBUSY;
2738
2739 flash->op_busy = 1;
2740 flash->cbfn = cbfn;
2741 flash->cbarg = cbarg;
2742 flash->ubuf = (u8 *) attr;
2743
2744 bfi_h2i_set(msg->mh, BFI_MC_FLASH, BFI_FLASH_H2I_QUERY_REQ,
2745 bfa_ioc_portid(flash->ioc));
2746 bfa_alen_set(&msg->alen, sizeof(struct bfa_flash_attr), flash->dbuf_pa);
2747 bfa_nw_ioc_mbox_queue(flash->ioc, &flash->mb, NULL, NULL);
2748
2749 return BFA_STATUS_OK;
2750}
2751
2752/*
2753 * Update flash partition.
2754 *
2755 * @param[in] flash - flash structure
2756 * @param[in] type - flash partition type
2757 * @param[in] instance - flash partition instance
2758 * @param[in] buf - update data buffer
2759 * @param[in] len - data buffer length
2760 * @param[in] offset - offset relative to the partition starting address
2761 * @param[in] cbfn - callback function
2762 * @param[in] cbarg - callback argument
2763 *
2764 * Return status.
2765 */
2766enum bfa_status
2767bfa_nw_flash_update_part(struct bfa_flash *flash, u32 type, u8 instance,
2768 void *buf, u32 len, u32 offset,
2769 bfa_cb_flash cbfn, void *cbarg)
2770{
2771 if (!bfa_nw_ioc_is_operational(flash->ioc))
2772 return BFA_STATUS_IOC_NON_OP;
2773
2774 /*
2775 * 'len' must be in word (4-byte) boundary
2776 */
2777 if (!len || (len & 0x03))
2778 return BFA_STATUS_FLASH_BAD_LEN;
2779
2780 if (type == BFA_FLASH_PART_MFG)
2781 return BFA_STATUS_EINVAL;
2782
2783 if (flash->op_busy)
2784 return BFA_STATUS_DEVBUSY;
2785
2786 flash->op_busy = 1;
2787 flash->cbfn = cbfn;
2788 flash->cbarg = cbarg;
2789 flash->type = type;
2790 flash->instance = instance;
2791 flash->residue = len;
2792 flash->offset = 0;
2793 flash->addr_off = offset;
2794 flash->ubuf = buf;
2795
2796 bfa_flash_write_send(flash);
2797
2798 return BFA_STATUS_OK;
2799}
2800
2801/*
2802 * Read flash partition.
2803 *
2804 * @param[in] flash - flash structure
2805 * @param[in] type - flash partition type
2806 * @param[in] instance - flash partition instance
2807 * @param[in] buf - read data buffer
2808 * @param[in] len - data buffer length
2809 * @param[in] offset - offset relative to the partition starting address
2810 * @param[in] cbfn - callback function
2811 * @param[in] cbarg - callback argument
2812 *
2813 * Return status.
2814 */
2815enum bfa_status
2816bfa_nw_flash_read_part(struct bfa_flash *flash, u32 type, u8 instance,
2817 void *buf, u32 len, u32 offset,
2818 bfa_cb_flash cbfn, void *cbarg)
2819{
2820 if (!bfa_nw_ioc_is_operational(flash->ioc))
2821 return BFA_STATUS_IOC_NON_OP;
2822
2823 /*
2824 * 'len' must be in word (4-byte) boundary
2825 */
2826 if (!len || (len & 0x03))
2827 return BFA_STATUS_FLASH_BAD_LEN;
2828
2829 if (flash->op_busy)
2830 return BFA_STATUS_DEVBUSY;
2831
2832 flash->op_busy = 1;
2833 flash->cbfn = cbfn;
2834 flash->cbarg = cbarg;
2835 flash->type = type;
2836 flash->instance = instance;
2837 flash->residue = len;
2838 flash->offset = 0;
2839 flash->addr_off = offset;
2840 flash->ubuf = buf;
2841
2842 bfa_flash_read_send(flash);
2843
2844 return BFA_STATUS_OK;
2845}
diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.h b/drivers/net/ethernet/brocade/bna/bfa_ioc.h
index ca158d1eaef3..fc108c7a735e 100644
--- a/drivers/net/ethernet/brocade/bna/bfa_ioc.h
+++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.h
@@ -68,6 +68,16 @@ __bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa)
68 dma_addr->a32.addr_hi = (u32) htonl(upper_32_bits(pa)); 68 dma_addr->a32.addr_hi = (u32) htonl(upper_32_bits(pa));
69} 69}
70 70
71#define bfa_alen_set(__alen, __len, __pa) \
72 __bfa_alen_set(__alen, __len, (u64)__pa)
73
74static inline void
75__bfa_alen_set(struct bfi_alen *alen, u32 len, u64 pa)
76{
77 alen->al_len = cpu_to_be32(len);
78 bfa_dma_be_addr_set(alen->al_addr, pa);
79}
80
71struct bfa_ioc_regs { 81struct bfa_ioc_regs {
72 void __iomem *hfn_mbox_cmd; 82 void __iomem *hfn_mbox_cmd;
73 void __iomem *hfn_mbox; 83 void __iomem *hfn_mbox;
@@ -322,4 +332,42 @@ void bfa_nw_iocpf_sem_timeout(void *ioc);
322u32 *bfa_cb_image_get_chunk(enum bfi_asic_gen asic_gen, u32 off); 332u32 *bfa_cb_image_get_chunk(enum bfi_asic_gen asic_gen, u32 off);
323u32 bfa_cb_image_get_size(enum bfi_asic_gen asic_gen); 333u32 bfa_cb_image_get_size(enum bfi_asic_gen asic_gen);
324 334
335/*
336 * Flash module specific
337 */
338typedef void (*bfa_cb_flash) (void *cbarg, enum bfa_status status);
339
340struct bfa_flash {
341 struct bfa_ioc *ioc; /* back pointer to ioc */
342 u32 type; /* partition type */
343 u8 instance; /* partition instance */
344 u8 rsv[3];
345 u32 op_busy; /* operation busy flag */
346 u32 residue; /* residual length */
347 u32 offset; /* offset */
348 enum bfa_status status; /* status */
349 u8 *dbuf_kva; /* dma buf virtual address */
350 u64 dbuf_pa; /* dma buf physical address */
351 bfa_cb_flash cbfn; /* user callback function */
352 void *cbarg; /* user callback arg */
353 u8 *ubuf; /* user supplied buffer */
354 u32 addr_off; /* partition address offset */
355 struct bfa_mbox_cmd mb; /* mailbox */
356 struct bfa_ioc_notify ioc_notify; /* ioc event notify */
357};
358
359enum bfa_status bfa_nw_flash_get_attr(struct bfa_flash *flash,
360 struct bfa_flash_attr *attr,
361 bfa_cb_flash cbfn, void *cbarg);
362enum bfa_status bfa_nw_flash_update_part(struct bfa_flash *flash,
363 u32 type, u8 instance, void *buf, u32 len, u32 offset,
364 bfa_cb_flash cbfn, void *cbarg);
365enum bfa_status bfa_nw_flash_read_part(struct bfa_flash *flash,
366 u32 type, u8 instance, void *buf, u32 len, u32 offset,
367 bfa_cb_flash cbfn, void *cbarg);
368u32 bfa_nw_flash_meminfo(void);
369void bfa_nw_flash_attach(struct bfa_flash *flash,
370 struct bfa_ioc *ioc, void *dev);
371void bfa_nw_flash_memclaim(struct bfa_flash *flash, u8 *dm_kva, u64 dm_pa);
372
325#endif /* __BFA_IOC_H__ */ 373#endif /* __BFA_IOC_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bfi.h b/drivers/net/ethernet/brocade/bna/bfi.h
index 7a1393aabd43..8230970ad2d3 100644
--- a/drivers/net/ethernet/brocade/bna/bfi.h
+++ b/drivers/net/ethernet/brocade/bna/bfi.h
@@ -83,6 +83,14 @@ union bfi_addr_u {
83 } a32; 83 } a32;
84}; 84};
85 85
86/**
87 * Generic DMA addr-len pair.
88 */
89struct bfi_alen {
90 union bfi_addr_u al_addr; /* DMA addr of buffer */
91 u32 al_len; /* length of buffer */
92};
93
86/* 94/*
87 * Large Message structure - 128 Bytes size Msgs 95 * Large Message structure - 128 Bytes size Msgs
88 */ 96 */
@@ -476,6 +484,93 @@ struct bfi_msgq_i2h_cmdq_copy_req {
476 u16 len; 484 u16 len;
477}; 485};
478 486
487/*
488 * FLASH module specific
489 */
490enum bfi_flash_h2i_msgs {
491 BFI_FLASH_H2I_QUERY_REQ = 1,
492 BFI_FLASH_H2I_ERASE_REQ = 2,
493 BFI_FLASH_H2I_WRITE_REQ = 3,
494 BFI_FLASH_H2I_READ_REQ = 4,
495 BFI_FLASH_H2I_BOOT_VER_REQ = 5,
496};
497
498enum bfi_flash_i2h_msgs {
499 BFI_FLASH_I2H_QUERY_RSP = BFA_I2HM(1),
500 BFI_FLASH_I2H_ERASE_RSP = BFA_I2HM(2),
501 BFI_FLASH_I2H_WRITE_RSP = BFA_I2HM(3),
502 BFI_FLASH_I2H_READ_RSP = BFA_I2HM(4),
503 BFI_FLASH_I2H_BOOT_VER_RSP = BFA_I2HM(5),
504 BFI_FLASH_I2H_EVENT = BFA_I2HM(127),
505};
506
507/*
508 * Flash query request
509 */
510struct bfi_flash_query_req {
511 struct bfi_mhdr mh; /* Common msg header */
512 struct bfi_alen alen;
513};
514
515/*
516 * Flash write request
517 */
518struct bfi_flash_write_req {
519 struct bfi_mhdr mh; /* Common msg header */
520 struct bfi_alen alen;
521 u32 type; /* partition type */
522 u8 instance; /* partition instance */
523 u8 last;
524 u8 rsv[2];
525 u32 offset;
526 u32 length;
527};
528
529/*
530 * Flash read request
531 */
532struct bfi_flash_read_req {
533 struct bfi_mhdr mh; /* Common msg header */
534 u32 type; /* partition type */
535 u8 instance; /* partition instance */
536 u8 rsv[3];
537 u32 offset;
538 u32 length;
539 struct bfi_alen alen;
540};
541
542/*
543 * Flash query response
544 */
545struct bfi_flash_query_rsp {
546 struct bfi_mhdr mh; /* Common msg header */
547 u32 status;
548};
549
550/*
551 * Flash read response
552 */
553struct bfi_flash_read_rsp {
554 struct bfi_mhdr mh; /* Common msg header */
555 u32 type; /* partition type */
556 u8 instance; /* partition instance */
557 u8 rsv[3];
558 u32 status;
559 u32 length;
560};
561
562/*
563 * Flash write response
564 */
565struct bfi_flash_write_rsp {
566 struct bfi_mhdr mh; /* Common msg header */
567 u32 type; /* partition type */
568 u8 instance; /* partition instance */
569 u8 rsv[3];
570 u32 status;
571 u32 length;
572};
573
479#pragma pack() 574#pragma pack()
480 575
481#endif /* __BFI_H__ */ 576#endif /* __BFI_H__ */
diff --git a/drivers/net/ethernet/brocade/bna/bna_enet.c b/drivers/net/ethernet/brocade/bna/bna_enet.c
index 26f5c5abfd1f..bcfe29676677 100644
--- a/drivers/net/ethernet/brocade/bna/bna_enet.c
+++ b/drivers/net/ethernet/brocade/bna/bna_enet.c
@@ -1740,6 +1740,11 @@ bna_ioceth_init(struct bna_ioceth *ioceth, struct bna *bna,
1740 kva += bfa_nw_cee_meminfo(); 1740 kva += bfa_nw_cee_meminfo();
1741 dma += bfa_nw_cee_meminfo(); 1741 dma += bfa_nw_cee_meminfo();
1742 1742
1743 bfa_nw_flash_attach(&bna->flash, &ioceth->ioc, bna);
1744 bfa_nw_flash_memclaim(&bna->flash, kva, dma);
1745 kva += bfa_nw_flash_meminfo();
1746 dma += bfa_nw_flash_meminfo();
1747
1743 bfa_msgq_attach(&bna->msgq, &ioceth->ioc); 1748 bfa_msgq_attach(&bna->msgq, &ioceth->ioc);
1744 bfa_msgq_memclaim(&bna->msgq, kva, dma); 1749 bfa_msgq_memclaim(&bna->msgq, kva, dma);
1745 bfa_msgq_regisr(&bna->msgq, BFI_MC_ENET, bna_msgq_rsp_handler, bna); 1750 bfa_msgq_regisr(&bna->msgq, BFI_MC_ENET, bna_msgq_rsp_handler, bna);
@@ -1892,7 +1897,8 @@ bna_res_req(struct bna_res_info *res_info)
1892 res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1; 1897 res_info[BNA_RES_MEM_T_COM].res_u.mem_info.num = 1;
1893 res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN( 1898 res_info[BNA_RES_MEM_T_COM].res_u.mem_info.len = ALIGN(
1894 (bfa_nw_cee_meminfo() + 1899 (bfa_nw_cee_meminfo() +
1895 bfa_msgq_meminfo()), PAGE_SIZE); 1900 bfa_nw_flash_meminfo() +
1901 bfa_msgq_meminfo()), PAGE_SIZE);
1896 1902
1897 /* DMA memory for retrieving IOC attributes */ 1903 /* DMA memory for retrieving IOC attributes */
1898 res_info[BNA_RES_MEM_T_ATTR].res_type = BNA_RES_T_MEM; 1904 res_info[BNA_RES_MEM_T_ATTR].res_type = BNA_RES_T_MEM;
diff --git a/drivers/net/ethernet/brocade/bna/bna_types.h b/drivers/net/ethernet/brocade/bna/bna_types.h
index d090fbfb12fa..8e57fc5c5868 100644
--- a/drivers/net/ethernet/brocade/bna/bna_types.h
+++ b/drivers/net/ethernet/brocade/bna/bna_types.h
@@ -966,6 +966,7 @@ struct bna {
966 966
967 struct bna_ioceth ioceth; 967 struct bna_ioceth ioceth;
968 struct bfa_cee cee; 968 struct bfa_cee cee;
969 struct bfa_flash flash;
969 struct bfa_msgq msgq; 970 struct bfa_msgq msgq;
970 971
971 struct bna_ethport ethport; 972 struct bna_ethport ethport;
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 197af04ff1ab..741f2e405006 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -48,7 +48,9 @@ MODULE_PARM_DESC(bnad_ioc_auto_recover, "Enable / Disable auto recovery");
48 * Global variables 48 * Global variables
49 */ 49 */
50u32 bnad_rxqs_per_cq = 2; 50u32 bnad_rxqs_per_cq = 2;
51 51u32 bna_id;
52struct mutex bnad_list_mutex;
53LIST_HEAD(bnad_list);
52static const u8 bnad_bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 54static const u8 bnad_bcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
53 55
54/* 56/*
@@ -75,6 +77,23 @@ do { \
75 77
76#define BNAD_TXRX_SYNC_MDELAY 250 /* 250 msecs */ 78#define BNAD_TXRX_SYNC_MDELAY 250 /* 250 msecs */
77 79
80static void
81bnad_add_to_list(struct bnad *bnad)
82{
83 mutex_lock(&bnad_list_mutex);
84 list_add_tail(&bnad->list_entry, &bnad_list);
85 bnad->id = bna_id++;
86 mutex_unlock(&bnad_list_mutex);
87}
88
89static void
90bnad_remove_from_list(struct bnad *bnad)
91{
92 mutex_lock(&bnad_list_mutex);
93 list_del(&bnad->list_entry);
94 mutex_unlock(&bnad_list_mutex);
95}
96
78/* 97/*
79 * Reinitialize completions in CQ, once Rx is taken down 98 * Reinitialize completions in CQ, once Rx is taken down
80 */ 99 */
@@ -1084,6 +1103,16 @@ bnad_cb_enet_mtu_set(struct bnad *bnad)
1084 complete(&bnad->bnad_completions.mtu_comp); 1103 complete(&bnad->bnad_completions.mtu_comp);
1085} 1104}
1086 1105
1106void
1107bnad_cb_completion(void *arg, enum bfa_status status)
1108{
1109 struct bnad_iocmd_comp *iocmd_comp =
1110 (struct bnad_iocmd_comp *)arg;
1111
1112 iocmd_comp->comp_status = (u32) status;
1113 complete(&iocmd_comp->comp);
1114}
1115
1087/* Resource allocation, free functions */ 1116/* Resource allocation, free functions */
1088 1117
1089static void 1118static void
@@ -3167,12 +3196,14 @@ bnad_lock_init(struct bnad *bnad)
3167{ 3196{
3168 spin_lock_init(&bnad->bna_lock); 3197 spin_lock_init(&bnad->bna_lock);
3169 mutex_init(&bnad->conf_mutex); 3198 mutex_init(&bnad->conf_mutex);
3199 mutex_init(&bnad_list_mutex);
3170} 3200}
3171 3201
3172static void 3202static void
3173bnad_lock_uninit(struct bnad *bnad) 3203bnad_lock_uninit(struct bnad *bnad)
3174{ 3204{
3175 mutex_destroy(&bnad->conf_mutex); 3205 mutex_destroy(&bnad->conf_mutex);
3206 mutex_destroy(&bnad_list_mutex);
3176} 3207}
3177 3208
3178/* PCI Initialization */ 3209/* PCI Initialization */
@@ -3253,8 +3284,8 @@ bnad_pci_probe(struct pci_dev *pdev,
3253 return err; 3284 return err;
3254 } 3285 }
3255 bnad = netdev_priv(netdev); 3286 bnad = netdev_priv(netdev);
3256
3257 bnad_lock_init(bnad); 3287 bnad_lock_init(bnad);
3288 bnad_add_to_list(bnad);
3258 3289
3259 mutex_lock(&bnad->conf_mutex); 3290 mutex_lock(&bnad->conf_mutex);
3260 /* 3291 /*
@@ -3407,6 +3438,7 @@ pci_uninit:
3407 bnad_pci_uninit(pdev); 3438 bnad_pci_uninit(pdev);
3408unlock_mutex: 3439unlock_mutex:
3409 mutex_unlock(&bnad->conf_mutex); 3440 mutex_unlock(&bnad->conf_mutex);
3441 bnad_remove_from_list(bnad);
3410 bnad_lock_uninit(bnad); 3442 bnad_lock_uninit(bnad);
3411 free_netdev(netdev); 3443 free_netdev(netdev);
3412 return err; 3444 return err;
@@ -3445,6 +3477,7 @@ bnad_pci_remove(struct pci_dev *pdev)
3445 bnad_disable_msix(bnad); 3477 bnad_disable_msix(bnad);
3446 bnad_pci_uninit(pdev); 3478 bnad_pci_uninit(pdev);
3447 mutex_unlock(&bnad->conf_mutex); 3479 mutex_unlock(&bnad->conf_mutex);
3480 bnad_remove_from_list(bnad);
3448 bnad_lock_uninit(bnad); 3481 bnad_lock_uninit(bnad);
3449 bnad_uninit(bnad); 3482 bnad_uninit(bnad);
3450 free_netdev(netdev); 3483 free_netdev(netdev);
diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h
index 5487ca42d018..459030c191c5 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.h
+++ b/drivers/net/ethernet/brocade/bna/bnad.h
@@ -124,6 +124,12 @@ enum bnad_link_state {
124 BNAD_LS_UP = 1 124 BNAD_LS_UP = 1
125}; 125};
126 126
127struct bnad_iocmd_comp {
128 struct bnad *bnad;
129 struct completion comp;
130 int comp_status;
131};
132
127struct bnad_completion { 133struct bnad_completion {
128 struct completion ioc_comp; 134 struct completion ioc_comp;
129 struct completion ucast_comp; 135 struct completion ucast_comp;
@@ -251,6 +257,8 @@ struct bnad_unmap_q {
251 257
252struct bnad { 258struct bnad {
253 struct net_device *netdev; 259 struct net_device *netdev;
260 u32 id;
261 struct list_head list_entry;
254 262
255 /* Data path */ 263 /* Data path */
256 struct bnad_tx_info tx_info[BNAD_MAX_TX]; 264 struct bnad_tx_info tx_info[BNAD_MAX_TX];
@@ -340,6 +348,7 @@ extern int bnad_mac_addr_set_locked(struct bnad *bnad, u8 *mac_addr);
340extern int bnad_enable_default_bcast(struct bnad *bnad); 348extern int bnad_enable_default_bcast(struct bnad *bnad);
341extern void bnad_restore_vlans(struct bnad *bnad, u32 rx_id); 349extern void bnad_restore_vlans(struct bnad *bnad, u32 rx_id);
342extern void bnad_set_ethtool_ops(struct net_device *netdev); 350extern void bnad_set_ethtool_ops(struct net_device *netdev);
351extern void bnad_cb_completion(void *arg, enum bfa_status status);
343 352
344/* Configuration & setup */ 353/* Configuration & setup */
345extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad); 354extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad);
diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
index 38d5c66075f9..5f7be5ac32a1 100644
--- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
+++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c
@@ -935,6 +935,143 @@ bnad_get_sset_count(struct net_device *netdev, int sset)
935 } 935 }
936} 936}
937 937
938static u32
939bnad_get_flash_partition_by_offset(struct bnad *bnad, u32 offset,
940 u32 *base_offset)
941{
942 struct bfa_flash_attr *flash_attr;
943 struct bnad_iocmd_comp fcomp;
944 u32 i, flash_part = 0, ret;
945 unsigned long flags = 0;
946
947 flash_attr = kzalloc(sizeof(struct bfa_flash_attr), GFP_KERNEL);
948 if (!flash_attr)
949 return -ENOMEM;
950
951 fcomp.bnad = bnad;
952 fcomp.comp_status = 0;
953
954 init_completion(&fcomp.comp);
955 spin_lock_irqsave(&bnad->bna_lock, flags);
956 ret = bfa_nw_flash_get_attr(&bnad->bna.flash, flash_attr,
957 bnad_cb_completion, &fcomp);
958 if (ret != BFA_STATUS_OK) {
959 spin_unlock_irqrestore(&bnad->bna_lock, flags);
960 kfree(flash_attr);
961 goto out_err;
962 }
963 spin_unlock_irqrestore(&bnad->bna_lock, flags);
964 wait_for_completion(&fcomp.comp);
965 ret = fcomp.comp_status;
966
967 /* Check for the flash type & base offset value */
968 if (ret == BFA_STATUS_OK) {
969 for (i = 0; i < flash_attr->npart; i++) {
970 if (offset >= flash_attr->part[i].part_off &&
971 offset < (flash_attr->part[i].part_off +
972 flash_attr->part[i].part_size)) {
973 flash_part = flash_attr->part[i].part_type;
974 *base_offset = flash_attr->part[i].part_off;
975 break;
976 }
977 }
978 }
979 kfree(flash_attr);
980 return flash_part;
981out_err:
982 return -EINVAL;
983}
984
985static int
986bnad_get_eeprom_len(struct net_device *netdev)
987{
988 return BFA_TOTAL_FLASH_SIZE;
989}
990
991static int
992bnad_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
993 u8 *bytes)
994{
995 struct bnad *bnad = netdev_priv(netdev);
996 struct bnad_iocmd_comp fcomp;
997 u32 flash_part = 0, base_offset = 0;
998 unsigned long flags = 0;
999 int ret = 0;
1000
1001 /* Check if the flash read request is valid */
1002 if (eeprom->magic != (bnad->pcidev->vendor |
1003 (bnad->pcidev->device << 16)))
1004 return -EFAULT;
1005
1006 /* Query the flash partition based on the offset */
1007 flash_part = bnad_get_flash_partition_by_offset(bnad,
1008 eeprom->offset, &base_offset);
1009 if (flash_part <= 0)
1010 return -EFAULT;
1011
1012 fcomp.bnad = bnad;
1013 fcomp.comp_status = 0;
1014
1015 init_completion(&fcomp.comp);
1016 spin_lock_irqsave(&bnad->bna_lock, flags);
1017 ret = bfa_nw_flash_read_part(&bnad->bna.flash, flash_part,
1018 bnad->id, bytes, eeprom->len,
1019 eeprom->offset - base_offset,
1020 bnad_cb_completion, &fcomp);
1021 if (ret != BFA_STATUS_OK) {
1022 spin_unlock_irqrestore(&bnad->bna_lock, flags);
1023 goto done;
1024 }
1025
1026 spin_unlock_irqrestore(&bnad->bna_lock, flags);
1027 wait_for_completion(&fcomp.comp);
1028 ret = fcomp.comp_status;
1029done:
1030 return ret;
1031}
1032
1033static int
1034bnad_set_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom,
1035 u8 *bytes)
1036{
1037 struct bnad *bnad = netdev_priv(netdev);
1038 struct bnad_iocmd_comp fcomp;
1039 u32 flash_part = 0, base_offset = 0;
1040 unsigned long flags = 0;
1041 int ret = 0;
1042
1043 /* Check if the flash update request is valid */
1044 if (eeprom->magic != (bnad->pcidev->vendor |
1045 (bnad->pcidev->device << 16)))
1046 return -EINVAL;
1047
1048 /* Query the flash partition based on the offset */
1049 flash_part = bnad_get_flash_partition_by_offset(bnad,
1050 eeprom->offset, &base_offset);
1051 if (flash_part <= 0)
1052 return -EFAULT;
1053
1054 fcomp.bnad = bnad;
1055 fcomp.comp_status = 0;
1056
1057 init_completion(&fcomp.comp);
1058 spin_lock_irqsave(&bnad->bna_lock, flags);
1059 ret = bfa_nw_flash_update_part(&bnad->bna.flash, flash_part,
1060 bnad->id, bytes, eeprom->len,
1061 eeprom->offset - base_offset,
1062 bnad_cb_completion, &fcomp);
1063 if (ret != BFA_STATUS_OK) {
1064 spin_unlock_irqrestore(&bnad->bna_lock, flags);
1065 goto done;
1066 }
1067
1068 spin_unlock_irqrestore(&bnad->bna_lock, flags);
1069 wait_for_completion(&fcomp.comp);
1070 ret = fcomp.comp_status;
1071done:
1072 return ret;
1073}
1074
938static struct ethtool_ops bnad_ethtool_ops = { 1075static struct ethtool_ops bnad_ethtool_ops = {
939 .get_settings = bnad_get_settings, 1076 .get_settings = bnad_get_settings,
940 .set_settings = bnad_set_settings, 1077 .set_settings = bnad_set_settings,
@@ -949,7 +1086,10 @@ static struct ethtool_ops bnad_ethtool_ops = {
949 .set_pauseparam = bnad_set_pauseparam, 1086 .set_pauseparam = bnad_set_pauseparam,
950 .get_strings = bnad_get_strings, 1087 .get_strings = bnad_get_strings,
951 .get_ethtool_stats = bnad_get_ethtool_stats, 1088 .get_ethtool_stats = bnad_get_ethtool_stats,
952 .get_sset_count = bnad_get_sset_count 1089 .get_sset_count = bnad_get_sset_count,
1090 .get_eeprom_len = bnad_get_eeprom_len,
1091 .get_eeprom = bnad_get_eeprom,
1092 .set_eeprom = bnad_set_eeprom,
953}; 1093};
954 1094
955void 1095void