.. | .. |
---|
198 | 198 | if (pcie_fw & PCIE_FW_ERR_F) { |
---|
199 | 199 | dev_err(adap->pdev_dev, "Firmware reports adapter error: %s\n", |
---|
200 | 200 | reason[PCIE_FW_EVAL_G(pcie_fw)]); |
---|
201 | | - adap->flags &= ~FW_OK; |
---|
| 201 | + adap->flags &= ~CXGB4_FW_OK; |
---|
202 | 202 | } |
---|
203 | 203 | } |
---|
204 | 204 | |
---|
.. | .. |
---|
329 | 329 | for (i = 0; ; i += ms) { |
---|
330 | 330 | /* If we've waited too long, return a busy indication. This |
---|
331 | 331 | * really ought to be based on our initial position in the |
---|
332 | | - * mailbox access list but this is a start. We very rearely |
---|
| 332 | + * mailbox access list but this is a start. We very rarely |
---|
333 | 333 | * contend on access to the mailbox ... |
---|
334 | 334 | */ |
---|
335 | 335 | pcie_fw = t4_read_reg(adap, PCIE_FW_A); |
---|
.. | .. |
---|
606 | 606 | * |
---|
607 | 607 | * Reads/writes an [almost] arbitrary memory region in the firmware: the |
---|
608 | 608 | * firmware memory address and host buffer must be aligned on 32-bit |
---|
609 | | - * boudaries; the length may be arbitrary. The memory is transferred as |
---|
| 609 | + * boundaries; the length may be arbitrary. The memory is transferred as |
---|
610 | 610 | * a raw byte sequence from/to the firmware's memory. If this memory |
---|
611 | 611 | * contains data structures which contain multi-byte integers, it's the |
---|
612 | 612 | * caller's responsibility to perform appropriate byte order conversions. |
---|
.. | .. |
---|
1379 | 1379 | 0x9608, 0x9638, |
---|
1380 | 1380 | 0x9640, 0x96f4, |
---|
1381 | 1381 | 0x9800, 0x9808, |
---|
1382 | | - 0x9820, 0x983c, |
---|
1383 | | - 0x9850, 0x9864, |
---|
| 1382 | + 0x9810, 0x9864, |
---|
1384 | 1383 | 0x9c00, 0x9c6c, |
---|
1385 | 1384 | 0x9c80, 0x9cec, |
---|
1386 | 1385 | 0x9d00, 0x9d6c, |
---|
.. | .. |
---|
1389 | 1388 | 0x9e80, 0x9eec, |
---|
1390 | 1389 | 0x9f00, 0x9f6c, |
---|
1391 | 1390 | 0x9f80, 0xa020, |
---|
1392 | | - 0xd004, 0xd004, |
---|
| 1391 | + 0xd000, 0xd004, |
---|
1393 | 1392 | 0xd010, 0xd03c, |
---|
1394 | 1393 | 0xdfc0, 0xdfe0, |
---|
1395 | 1394 | 0xe000, 0x1106c, |
---|
.. | .. |
---|
1430 | 1429 | 0x1a0b0, 0x1a0e4, |
---|
1431 | 1430 | 0x1a0ec, 0x1a0f8, |
---|
1432 | 1431 | 0x1a100, 0x1a108, |
---|
1433 | | - 0x1a114, 0x1a120, |
---|
1434 | | - 0x1a128, 0x1a130, |
---|
1435 | | - 0x1a138, 0x1a138, |
---|
1436 | | - 0x1a190, 0x1a1c4, |
---|
| 1432 | + 0x1a114, 0x1a130, |
---|
| 1433 | + 0x1a138, 0x1a1c4, |
---|
1437 | 1434 | 0x1a1fc, 0x1a1fc, |
---|
1438 | 1435 | 0x1e008, 0x1e00c, |
---|
1439 | 1436 | 0x1e040, 0x1e044, |
---|
.. | .. |
---|
2163 | 2160 | 0x9640, 0x9704, |
---|
2164 | 2161 | 0x9710, 0x971c, |
---|
2165 | 2162 | 0x9800, 0x9808, |
---|
2166 | | - 0x9820, 0x983c, |
---|
2167 | | - 0x9850, 0x9864, |
---|
| 2163 | + 0x9810, 0x9864, |
---|
2168 | 2164 | 0x9c00, 0x9c6c, |
---|
2169 | 2165 | 0x9c80, 0x9cec, |
---|
2170 | 2166 | 0x9d00, 0x9d6c, |
---|
.. | .. |
---|
2173 | 2169 | 0x9e80, 0x9eec, |
---|
2174 | 2170 | 0x9f00, 0x9f6c, |
---|
2175 | 2171 | 0x9f80, 0xa020, |
---|
2176 | | - 0xd004, 0xd03c, |
---|
| 2172 | + 0xd000, 0xd03c, |
---|
2177 | 2173 | 0xd100, 0xd118, |
---|
2178 | 2174 | 0xd200, 0xd214, |
---|
2179 | 2175 | 0xd220, 0xd234, |
---|
.. | .. |
---|
2241 | 2237 | 0x1a0b0, 0x1a0e4, |
---|
2242 | 2238 | 0x1a0ec, 0x1a0f8, |
---|
2243 | 2239 | 0x1a100, 0x1a108, |
---|
2244 | | - 0x1a114, 0x1a120, |
---|
2245 | | - 0x1a128, 0x1a130, |
---|
2246 | | - 0x1a138, 0x1a138, |
---|
2247 | | - 0x1a190, 0x1a1c4, |
---|
| 2240 | + 0x1a114, 0x1a130, |
---|
| 2241 | + 0x1a138, 0x1a1c4, |
---|
2248 | 2242 | 0x1a1fc, 0x1a1fc, |
---|
2249 | 2243 | 0x1e008, 0x1e00c, |
---|
2250 | 2244 | 0x1e040, 0x1e044, |
---|
.. | .. |
---|
3073 | 3067 | * @addr: the start address to write |
---|
3074 | 3068 | * @n: length of data to write in bytes |
---|
3075 | 3069 | * @data: the data to write |
---|
| 3070 | + * @byte_oriented: whether to store data as bytes or as words |
---|
3076 | 3071 | * |
---|
3077 | 3072 | * Writes up to a page of data (256 bytes) to the serial flash starting |
---|
3078 | 3073 | * at the given address. All the data must be written to the same page. |
---|
| 3074 | + * If @byte_oriented is set the write data is stored as byte stream |
---|
| 3075 | + * (i.e. matches what on disk), otherwise in big-endian. |
---|
3079 | 3076 | */ |
---|
3080 | 3077 | static int t4_write_flash(struct adapter *adapter, unsigned int addr, |
---|
3081 | | - unsigned int n, const u8 *data) |
---|
| 3078 | + unsigned int n, const u8 *data, bool byte_oriented) |
---|
3082 | 3079 | { |
---|
3083 | | - int ret; |
---|
3084 | | - u32 buf[64]; |
---|
3085 | 3080 | unsigned int i, c, left, val, offset = addr & 0xff; |
---|
| 3081 | + u32 buf[64]; |
---|
| 3082 | + int ret; |
---|
3086 | 3083 | |
---|
3087 | 3084 | if (addr >= adapter->params.sf_size || offset + n > SF_PAGE_SIZE) |
---|
3088 | 3085 | return -EINVAL; |
---|
.. | .. |
---|
3093 | 3090 | (ret = sf1_write(adapter, 4, 1, 1, val)) != 0) |
---|
3094 | 3091 | goto unlock; |
---|
3095 | 3092 | |
---|
3096 | | - for (left = n; left; left -= c) { |
---|
| 3093 | + for (left = n; left; left -= c, data += c) { |
---|
3097 | 3094 | c = min(left, 4U); |
---|
3098 | | - for (val = 0, i = 0; i < c; ++i) |
---|
3099 | | - val = (val << 8) + *data++; |
---|
| 3095 | + for (val = 0, i = 0; i < c; ++i) { |
---|
| 3096 | + if (byte_oriented) |
---|
| 3097 | + val = (val << 8) + data[i]; |
---|
| 3098 | + else |
---|
| 3099 | + val = (val << 8) + data[c - i - 1]; |
---|
| 3100 | + } |
---|
3100 | 3101 | |
---|
3101 | 3102 | ret = sf1_write(adapter, c, c != left, 1, val); |
---|
3102 | 3103 | if (ret) |
---|
.. | .. |
---|
3109 | 3110 | t4_write_reg(adapter, SF_OP_A, 0); /* unlock SF */ |
---|
3110 | 3111 | |
---|
3111 | 3112 | /* Read the page to verify the write succeeded */ |
---|
3112 | | - ret = t4_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf, 1); |
---|
| 3113 | + ret = t4_read_flash(adapter, addr & ~0xff, ARRAY_SIZE(buf), buf, |
---|
| 3114 | + byte_oriented); |
---|
3113 | 3115 | if (ret) |
---|
3114 | 3116 | return ret; |
---|
3115 | 3117 | |
---|
.. | .. |
---|
3170 | 3172 | |
---|
3171 | 3173 | /** |
---|
3172 | 3174 | * t4_get_exprom_version - return the Expansion ROM version (if any) |
---|
3173 | | - * @adapter: the adapter |
---|
| 3175 | + * @adap: the adapter |
---|
3174 | 3176 | * @vers: where to place the version |
---|
3175 | 3177 | * |
---|
3176 | 3178 | * Reads the Expansion ROM header from FLASH and returns the version |
---|
.. | .. |
---|
3705 | 3707 | */ |
---|
3706 | 3708 | memcpy(first_page, fw_data, SF_PAGE_SIZE); |
---|
3707 | 3709 | ((struct fw_hdr *)first_page)->fw_ver = cpu_to_be32(0xffffffff); |
---|
3708 | | - ret = t4_write_flash(adap, fw_start, SF_PAGE_SIZE, first_page); |
---|
| 3710 | + ret = t4_write_flash(adap, fw_start, SF_PAGE_SIZE, first_page, true); |
---|
3709 | 3711 | if (ret) |
---|
3710 | 3712 | goto out; |
---|
3711 | 3713 | |
---|
.. | .. |
---|
3713 | 3715 | for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) { |
---|
3714 | 3716 | addr += SF_PAGE_SIZE; |
---|
3715 | 3717 | fw_data += SF_PAGE_SIZE; |
---|
3716 | | - ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, fw_data); |
---|
| 3718 | + ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, fw_data, true); |
---|
3717 | 3719 | if (ret) |
---|
3718 | 3720 | goto out; |
---|
3719 | 3721 | } |
---|
3720 | 3722 | |
---|
3721 | | - ret = t4_write_flash(adap, |
---|
3722 | | - fw_start + offsetof(struct fw_hdr, fw_ver), |
---|
3723 | | - sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver); |
---|
| 3723 | + ret = t4_write_flash(adap, fw_start + offsetof(struct fw_hdr, fw_ver), |
---|
| 3724 | + sizeof(hdr->fw_ver), (const u8 *)&hdr->fw_ver, |
---|
| 3725 | + true); |
---|
3724 | 3726 | out: |
---|
3725 | 3727 | if (ret) |
---|
3726 | 3728 | dev_err(adap->pdev_dev, "firmware download failed, error %d\n", |
---|
.. | .. |
---|
3759 | 3761 | * t4_load_phy_fw - download port PHY firmware |
---|
3760 | 3762 | * @adap: the adapter |
---|
3761 | 3763 | * @win: the PCI-E Memory Window index to use for t4_memory_rw() |
---|
3762 | | - * @win_lock: the lock to use to guard the memory copy |
---|
3763 | 3764 | * @phy_fw_version: function to check PHY firmware versions |
---|
3764 | 3765 | * @phy_fw_data: the PHY firmware image to write |
---|
3765 | 3766 | * @phy_fw_size: image size |
---|
.. | .. |
---|
3768 | 3769 | * @phy_fw_version is supplied, then it will be used to determine if |
---|
3769 | 3770 | * it's necessary to perform the transfer by comparing the version |
---|
3770 | 3771 | * of any existing adapter PHY firmware with that of the passed in |
---|
3771 | | - * PHY firmware image. If @win_lock is non-NULL then it will be used |
---|
3772 | | - * around the call to t4_memory_rw() which transfers the PHY firmware |
---|
3773 | | - * to the adapter. |
---|
| 3772 | + * PHY firmware image. |
---|
3774 | 3773 | * |
---|
3775 | 3774 | * A negative error number will be returned if an error occurs. If |
---|
3776 | 3775 | * version number support is available and there's no need to upgrade |
---|
3777 | 3776 | * the firmware, 0 will be returned. If firmware is successfully |
---|
3778 | | - * transferred to the adapter, 1 will be retured. |
---|
| 3777 | + * transferred to the adapter, 1 will be returned. |
---|
3779 | 3778 | * |
---|
3780 | 3779 | * NOTE: some adapters only have local RAM to store the PHY firmware. As |
---|
3781 | 3780 | * a result, a RESET of the adapter would cause that RAM to lose its |
---|
3782 | 3781 | * contents. Thus, loading PHY firmware on such adapters must happen |
---|
3783 | 3782 | * after any FW_RESET_CMDs ... |
---|
3784 | 3783 | */ |
---|
3785 | | -int t4_load_phy_fw(struct adapter *adap, |
---|
3786 | | - int win, spinlock_t *win_lock, |
---|
| 3784 | +int t4_load_phy_fw(struct adapter *adap, int win, |
---|
3787 | 3785 | int (*phy_fw_version)(const u8 *, size_t), |
---|
3788 | 3786 | const u8 *phy_fw_data, size_t phy_fw_size) |
---|
3789 | 3787 | { |
---|
| 3788 | + int cur_phy_fw_ver = 0, new_phy_fw_vers = 0; |
---|
3790 | 3789 | unsigned long mtype = 0, maddr = 0; |
---|
3791 | 3790 | u32 param, val; |
---|
3792 | | - int cur_phy_fw_ver = 0, new_phy_fw_vers = 0; |
---|
3793 | 3791 | int ret; |
---|
3794 | 3792 | |
---|
3795 | 3793 | /* If we have version number support, then check to see if the adapter |
---|
3796 | 3794 | * already has up-to-date PHY firmware loaded. |
---|
3797 | 3795 | */ |
---|
3798 | | - if (phy_fw_version) { |
---|
| 3796 | + if (phy_fw_version) { |
---|
3799 | 3797 | new_phy_fw_vers = phy_fw_version(phy_fw_data, phy_fw_size); |
---|
3800 | 3798 | ret = t4_phy_fw_ver(adap, &cur_phy_fw_ver); |
---|
3801 | 3799 | if (ret < 0) |
---|
.. | .. |
---|
3809 | 3807 | } |
---|
3810 | 3808 | |
---|
3811 | 3809 | /* Ask the firmware where it wants us to copy the PHY firmware image. |
---|
3812 | | - * The size of the file requires a special version of the READ coommand |
---|
| 3810 | + * The size of the file requires a special version of the READ command |
---|
3813 | 3811 | * which will pass the file size via the values field in PARAMS_CMD and |
---|
3814 | 3812 | * retrieve the return value from firmware and place it in the same |
---|
3815 | 3813 | * buffer values |
---|
.. | .. |
---|
3829 | 3827 | /* Copy the supplied PHY Firmware image to the adapter memory location |
---|
3830 | 3828 | * allocated by the adapter firmware. |
---|
3831 | 3829 | */ |
---|
3832 | | - if (win_lock) |
---|
3833 | | - spin_lock_bh(win_lock); |
---|
| 3830 | + spin_lock_bh(&adap->win0_lock); |
---|
3834 | 3831 | ret = t4_memory_rw(adap, win, mtype, maddr, |
---|
3835 | 3832 | phy_fw_size, (__be32 *)phy_fw_data, |
---|
3836 | 3833 | T4_MEMORY_WRITE); |
---|
3837 | | - if (win_lock) |
---|
3838 | | - spin_unlock_bh(win_lock); |
---|
| 3834 | + spin_unlock_bh(&adap->win0_lock); |
---|
3839 | 3835 | if (ret) |
---|
3840 | 3836 | return ret; |
---|
3841 | 3837 | |
---|
.. | .. |
---|
3965 | 3961 | } |
---|
3966 | 3962 | } |
---|
3967 | 3963 | |
---|
| 3964 | +/* The ADVERT_MASK is used to mask out all of the Advertised Firmware Port |
---|
| 3965 | + * Capabilities which we control with separate controls -- see, for instance, |
---|
| 3966 | + * Pause Frames and Forward Error Correction. In order to determine what the |
---|
| 3967 | + * full set of Advertised Port Capabilities are, the base Advertised Port |
---|
| 3968 | + * Capabilities (masked by ADVERT_MASK) must be combined with the Advertised |
---|
| 3969 | + * Port Capabilities associated with those other controls. See |
---|
| 3970 | + * t4_link_acaps() for how this is done. |
---|
| 3971 | + */ |
---|
3968 | 3972 | #define ADVERT_MASK (FW_PORT_CAP32_SPEED_V(FW_PORT_CAP32_SPEED_M) | \ |
---|
3969 | 3973 | FW_PORT_CAP32_ANEG) |
---|
3970 | 3974 | |
---|
.. | .. |
---|
4062 | 4066 | /* Translate Common Code Pause specification into Firmware Port Capabilities */ |
---|
4063 | 4067 | static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause) |
---|
4064 | 4068 | { |
---|
| 4069 | + /* Translate orthogonal RX/TX Pause Controls for L1 Configure |
---|
| 4070 | + * commands, etc. |
---|
| 4071 | + */ |
---|
4065 | 4072 | fw_port_cap32_t fw_pause = 0; |
---|
4066 | 4073 | |
---|
4067 | 4074 | if (cc_pause & PAUSE_RX) |
---|
.. | .. |
---|
4070 | 4077 | fw_pause |= FW_PORT_CAP32_FC_TX; |
---|
4071 | 4078 | if (!(cc_pause & PAUSE_AUTONEG)) |
---|
4072 | 4079 | fw_pause |= FW_PORT_CAP32_FORCE_PAUSE; |
---|
| 4080 | + |
---|
| 4081 | + /* Translate orthogonal Pause controls into IEEE 802.3 Pause, |
---|
| 4082 | + * Asymmetrical Pause for use in reporting to upper layer OS code, etc. |
---|
| 4083 | + * Note that these bits are ignored in L1 Configure commands. |
---|
| 4084 | + */ |
---|
| 4085 | + if (cc_pause & PAUSE_RX) { |
---|
| 4086 | + if (cc_pause & PAUSE_TX) |
---|
| 4087 | + fw_pause |= FW_PORT_CAP32_802_3_PAUSE; |
---|
| 4088 | + else |
---|
| 4089 | + fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR | |
---|
| 4090 | + FW_PORT_CAP32_802_3_PAUSE; |
---|
| 4091 | + } else if (cc_pause & PAUSE_TX) { |
---|
| 4092 | + fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR; |
---|
| 4093 | + } |
---|
4073 | 4094 | |
---|
4074 | 4095 | return fw_pause; |
---|
4075 | 4096 | } |
---|
.. | .. |
---|
4101 | 4122 | } |
---|
4102 | 4123 | |
---|
4103 | 4124 | /** |
---|
4104 | | - * t4_link_l1cfg - apply link configuration to MAC/PHY |
---|
| 4125 | + * t4_link_acaps - compute Link Advertised Port Capabilities |
---|
4105 | 4126 | * @adapter: the adapter |
---|
4106 | | - * @mbox: the Firmware Mailbox to use |
---|
4107 | 4127 | * @port: the Port ID |
---|
4108 | 4128 | * @lc: the Port's Link Configuration |
---|
4109 | 4129 | * |
---|
4110 | | - * Set up a port's MAC and PHY according to a desired link configuration. |
---|
4111 | | - * - If the PHY can auto-negotiate first decide what to advertise, then |
---|
4112 | | - * enable/disable auto-negotiation as desired, and reset. |
---|
4113 | | - * - If the PHY does not auto-negotiate just reset it. |
---|
4114 | | - * - If auto-negotiation is off set the MAC to the proper speed/duplex/FC, |
---|
4115 | | - * otherwise do it later based on the outcome of auto-negotiation. |
---|
| 4130 | + * Synthesize the Advertised Port Capabilities we'll be using based on |
---|
| 4131 | + * the base Advertised Port Capabilities (which have been filtered by |
---|
| 4132 | + * ADVERT_MASK) plus the individual controls for things like Pause |
---|
| 4133 | + * Frames, Forward Error Correction, MDI, etc. |
---|
4116 | 4134 | */ |
---|
4117 | | -int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox, |
---|
4118 | | - unsigned int port, struct link_config *lc, |
---|
4119 | | - bool sleep_ok, int timeout) |
---|
| 4135 | +fw_port_cap32_t t4_link_acaps(struct adapter *adapter, unsigned int port, |
---|
| 4136 | + struct link_config *lc) |
---|
4120 | 4137 | { |
---|
4121 | | - unsigned int fw_caps = adapter->params.fw_caps_support; |
---|
4122 | | - fw_port_cap32_t fw_fc, cc_fec, fw_fec, rcap; |
---|
4123 | | - struct fw_port_cmd cmd; |
---|
| 4138 | + fw_port_cap32_t fw_fc, fw_fec, acaps; |
---|
4124 | 4139 | unsigned int fw_mdi; |
---|
4125 | | - int ret; |
---|
| 4140 | + char cc_fec; |
---|
4126 | 4141 | |
---|
4127 | 4142 | fw_mdi = (FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO) & lc->pcaps); |
---|
| 4143 | + |
---|
4128 | 4144 | /* Convert driver coding of Pause Frame Flow Control settings into the |
---|
4129 | 4145 | * Firmware's API. |
---|
4130 | 4146 | */ |
---|
.. | .. |
---|
4133 | 4149 | /* Convert Common Code Forward Error Control settings into the |
---|
4134 | 4150 | * Firmware's API. If the current Requested FEC has "Automatic" |
---|
4135 | 4151 | * (IEEE 802.3) specified, then we use whatever the Firmware |
---|
4136 | | - * sent us as part of it's IEEE 802.3-based interpratation of |
---|
| 4152 | + * sent us as part of its IEEE 802.3-based interpretation of |
---|
4137 | 4153 | * the Transceiver Module EPROM FEC parameters. Otherwise we |
---|
4138 | 4154 | * use whatever is in the current Requested FEC settings. |
---|
4139 | 4155 | */ |
---|
.. | .. |
---|
4144 | 4160 | fw_fec = cc_to_fwcap_fec(cc_fec); |
---|
4145 | 4161 | |
---|
4146 | 4162 | /* Figure out what our Requested Port Capabilities are going to be. |
---|
| 4163 | + * Note parallel structure in t4_handle_get_port_info() and |
---|
| 4164 | + * init_link_config(). |
---|
4147 | 4165 | */ |
---|
4148 | 4166 | if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) { |
---|
4149 | | - rcap = lc->acaps | fw_fc | fw_fec; |
---|
| 4167 | + acaps = lc->acaps | fw_fc | fw_fec; |
---|
4150 | 4168 | lc->fc = lc->requested_fc & ~PAUSE_AUTONEG; |
---|
4151 | 4169 | lc->fec = cc_fec; |
---|
4152 | 4170 | } else if (lc->autoneg == AUTONEG_DISABLE) { |
---|
4153 | | - rcap = lc->speed_caps | fw_fc | fw_fec | fw_mdi; |
---|
| 4171 | + acaps = lc->speed_caps | fw_fc | fw_fec | fw_mdi; |
---|
4154 | 4172 | lc->fc = lc->requested_fc & ~PAUSE_AUTONEG; |
---|
4155 | 4173 | lc->fec = cc_fec; |
---|
4156 | 4174 | } else { |
---|
4157 | | - rcap = lc->acaps | fw_fc | fw_fec | fw_mdi; |
---|
| 4175 | + acaps = lc->acaps | fw_fc | fw_fec | fw_mdi; |
---|
4158 | 4176 | } |
---|
4159 | 4177 | |
---|
4160 | | - /* Note that older Firmware doesn't have FW_PORT_CAP32_FORCE_PAUSE, so |
---|
| 4178 | + /* Some Requested Port Capabilities are trivially wrong if they exceed |
---|
| 4179 | + * the Physical Port Capabilities. We can check that here and provide |
---|
| 4180 | + * moderately useful feedback in the system log. |
---|
| 4181 | + * |
---|
| 4182 | + * Note that older Firmware doesn't have FW_PORT_CAP32_FORCE_PAUSE, so |
---|
4161 | 4183 | * we need to exclude this from this check in order to maintain |
---|
4162 | 4184 | * compatibility ... |
---|
4163 | 4185 | */ |
---|
4164 | | - if ((rcap & ~lc->pcaps) & ~FW_PORT_CAP32_FORCE_PAUSE) { |
---|
4165 | | - dev_err(adapter->pdev_dev, |
---|
4166 | | - "Requested Port Capabilities %#x exceed Physical Port Capabilities %#x\n", |
---|
4167 | | - rcap, lc->pcaps); |
---|
| 4186 | + if ((acaps & ~lc->pcaps) & ~FW_PORT_CAP32_FORCE_PAUSE) { |
---|
| 4187 | + dev_err(adapter->pdev_dev, "Requested Port Capabilities %#x exceed Physical Port Capabilities %#x\n", |
---|
| 4188 | + acaps, lc->pcaps); |
---|
4168 | 4189 | return -EINVAL; |
---|
4169 | 4190 | } |
---|
4170 | 4191 | |
---|
4171 | | - /* And send that on to the Firmware ... |
---|
| 4192 | + return acaps; |
---|
| 4193 | +} |
---|
| 4194 | + |
---|
| 4195 | +/** |
---|
| 4196 | + * t4_link_l1cfg_core - apply link configuration to MAC/PHY |
---|
| 4197 | + * @adapter: the adapter |
---|
| 4198 | + * @mbox: the Firmware Mailbox to use |
---|
| 4199 | + * @port: the Port ID |
---|
| 4200 | + * @lc: the Port's Link Configuration |
---|
| 4201 | + * @sleep_ok: if true we may sleep while awaiting command completion |
---|
| 4202 | + * @timeout: time to wait for command to finish before timing out |
---|
| 4203 | + * (negative implies @sleep_ok=false) |
---|
| 4204 | + * |
---|
| 4205 | + * Set up a port's MAC and PHY according to a desired link configuration. |
---|
| 4206 | + * - If the PHY can auto-negotiate first decide what to advertise, then |
---|
| 4207 | + * enable/disable auto-negotiation as desired, and reset. |
---|
| 4208 | + * - If the PHY does not auto-negotiate just reset it. |
---|
| 4209 | + * - If auto-negotiation is off set the MAC to the proper speed/duplex/FC, |
---|
| 4210 | + * otherwise do it later based on the outcome of auto-negotiation. |
---|
| 4211 | + */ |
---|
| 4212 | +int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox, |
---|
| 4213 | + unsigned int port, struct link_config *lc, |
---|
| 4214 | + u8 sleep_ok, int timeout) |
---|
| 4215 | +{ |
---|
| 4216 | + unsigned int fw_caps = adapter->params.fw_caps_support; |
---|
| 4217 | + struct fw_port_cmd cmd; |
---|
| 4218 | + fw_port_cap32_t rcap; |
---|
| 4219 | + int ret; |
---|
| 4220 | + |
---|
| 4221 | + if (!(lc->pcaps & FW_PORT_CAP32_ANEG) && |
---|
| 4222 | + lc->autoneg == AUTONEG_ENABLE) { |
---|
| 4223 | + return -EINVAL; |
---|
| 4224 | + } |
---|
| 4225 | + |
---|
| 4226 | + /* Compute our Requested Port Capabilities and send that on to the |
---|
| 4227 | + * Firmware. |
---|
4172 | 4228 | */ |
---|
| 4229 | + rcap = t4_link_acaps(adapter, port, lc); |
---|
4173 | 4230 | memset(&cmd, 0, sizeof(cmd)); |
---|
4174 | 4231 | cmd.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) | |
---|
4175 | 4232 | FW_CMD_REQUEST_F | FW_CMD_EXEC_F | |
---|
.. | .. |
---|
4186 | 4243 | |
---|
4187 | 4244 | ret = t4_wr_mbox_meat_timeout(adapter, mbox, &cmd, sizeof(cmd), NULL, |
---|
4188 | 4245 | sleep_ok, timeout); |
---|
| 4246 | + |
---|
| 4247 | + /* Unfortunately, even if the Requested Port Capabilities "fit" within |
---|
| 4248 | + * the Physical Port Capabilities, some combinations of features may |
---|
| 4249 | + * still not be legal. For example, 40Gb/s and Reed-Solomon Forward |
---|
| 4250 | + * Error Correction. So if the Firmware rejects the L1 Configure |
---|
| 4251 | + * request, flag that here. |
---|
| 4252 | + */ |
---|
4189 | 4253 | if (ret) { |
---|
4190 | 4254 | dev_err(adapter->pdev_dev, |
---|
4191 | 4255 | "Requested Port Capabilities %#x rejected, error %d\n", |
---|
4192 | 4256 | rcap, -ret); |
---|
4193 | 4257 | return ret; |
---|
4194 | 4258 | } |
---|
4195 | | - return ret; |
---|
| 4259 | + return 0; |
---|
4196 | 4260 | } |
---|
4197 | 4261 | |
---|
4198 | 4262 | /** |
---|
.. | .. |
---|
4205 | 4269 | */ |
---|
4206 | 4270 | int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port) |
---|
4207 | 4271 | { |
---|
| 4272 | + unsigned int fw_caps = adap->params.fw_caps_support; |
---|
4208 | 4273 | struct fw_port_cmd c; |
---|
4209 | 4274 | |
---|
4210 | 4275 | memset(&c, 0, sizeof(c)); |
---|
.. | .. |
---|
4212 | 4277 | FW_CMD_REQUEST_F | FW_CMD_EXEC_F | |
---|
4213 | 4278 | FW_PORT_CMD_PORTID_V(port)); |
---|
4214 | 4279 | c.action_to_len16 = |
---|
4215 | | - cpu_to_be32(FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_L1_CFG) | |
---|
| 4280 | + cpu_to_be32(FW_PORT_CMD_ACTION_V(fw_caps == FW_CAPS16 |
---|
| 4281 | + ? FW_PORT_ACTION_L1_CFG |
---|
| 4282 | + : FW_PORT_ACTION_L1_CFG32) | |
---|
4216 | 4283 | FW_LEN16(c)); |
---|
4217 | | - c.u.l1cfg.rcap = cpu_to_be32(FW_PORT_CAP32_ANEG); |
---|
| 4284 | + if (fw_caps == FW_CAPS16) |
---|
| 4285 | + c.u.l1cfg.rcap = cpu_to_be32(FW_PORT_CAP_ANEG); |
---|
| 4286 | + else |
---|
| 4287 | + c.u.l1cfg32.rcap32 = cpu_to_be32(FW_PORT_CAP32_ANEG); |
---|
4218 | 4288 | return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); |
---|
4219 | 4289 | } |
---|
4220 | 4290 | |
---|
.. | .. |
---|
4407 | 4477 | */ |
---|
4408 | 4478 | static void sge_intr_handler(struct adapter *adapter) |
---|
4409 | 4479 | { |
---|
4410 | | - u64 v; |
---|
| 4480 | + u32 v = 0, perr; |
---|
4411 | 4481 | u32 err; |
---|
4412 | 4482 | |
---|
4413 | 4483 | static const struct intr_info sge_intr_info[] = { |
---|
.. | .. |
---|
4442 | 4512 | { 0 } |
---|
4443 | 4513 | }; |
---|
4444 | 4514 | |
---|
4445 | | - v = (u64)t4_read_reg(adapter, SGE_INT_CAUSE1_A) | |
---|
4446 | | - ((u64)t4_read_reg(adapter, SGE_INT_CAUSE2_A) << 32); |
---|
4447 | | - if (v) { |
---|
4448 | | - dev_alert(adapter->pdev_dev, "SGE parity error (%#llx)\n", |
---|
4449 | | - (unsigned long long)v); |
---|
4450 | | - t4_write_reg(adapter, SGE_INT_CAUSE1_A, v); |
---|
4451 | | - t4_write_reg(adapter, SGE_INT_CAUSE2_A, v >> 32); |
---|
| 4515 | + perr = t4_read_reg(adapter, SGE_INT_CAUSE1_A); |
---|
| 4516 | + if (perr) { |
---|
| 4517 | + v |= perr; |
---|
| 4518 | + dev_alert(adapter->pdev_dev, "SGE Cause1 Parity Error %#x\n", |
---|
| 4519 | + perr); |
---|
| 4520 | + } |
---|
| 4521 | + |
---|
| 4522 | + perr = t4_read_reg(adapter, SGE_INT_CAUSE2_A); |
---|
| 4523 | + if (perr) { |
---|
| 4524 | + v |= perr; |
---|
| 4525 | + dev_alert(adapter->pdev_dev, "SGE Cause2 Parity Error %#x\n", |
---|
| 4526 | + perr); |
---|
| 4527 | + } |
---|
| 4528 | + |
---|
| 4529 | + if (CHELSIO_CHIP_VERSION(adapter->params.chip) >= CHELSIO_T5) { |
---|
| 4530 | + perr = t4_read_reg(adapter, SGE_INT_CAUSE5_A); |
---|
| 4531 | + /* Parity error (CRC) for err_T_RxCRC is trivial, ignore it */ |
---|
| 4532 | + perr &= ~ERR_T_RXCRC_F; |
---|
| 4533 | + if (perr) { |
---|
| 4534 | + v |= perr; |
---|
| 4535 | + dev_alert(adapter->pdev_dev, |
---|
| 4536 | + "SGE Cause5 Parity Error %#x\n", perr); |
---|
| 4537 | + } |
---|
4452 | 4538 | } |
---|
4453 | 4539 | |
---|
4454 | 4540 | v |= t4_handle_intr_status(adapter, SGE_INT_CAUSE3_A, sge_intr_info); |
---|
.. | .. |
---|
4670 | 4756 | static struct intr_info t6_le_intr_info[] = { |
---|
4671 | 4757 | { T6_LIPMISS_F, "LE LIP miss", -1, 0 }, |
---|
4672 | 4758 | { T6_LIP0_F, "LE 0 LIP error", -1, 0 }, |
---|
| 4759 | + { CMDTIDERR_F, "LE cmd tid error", -1, 1 }, |
---|
4673 | 4760 | { TCAMINTPERR_F, "LE parity error", -1, 1 }, |
---|
4674 | 4761 | { T6_UNKNOWNCMD_F, "LE unknown command", -1, 1 }, |
---|
4675 | 4762 | { SSRAMINTPERR_F, "LE request queue parity error", -1, 1 }, |
---|
| 4763 | + { HASHTBLMEMCRCERR_F, "LE hash table mem crc error", -1, 0 }, |
---|
4676 | 4764 | { 0 } |
---|
4677 | 4765 | }; |
---|
4678 | 4766 | |
---|
.. | .. |
---|
4937 | 5025 | */ |
---|
4938 | 5026 | int t4_slow_intr_handler(struct adapter *adapter) |
---|
4939 | 5027 | { |
---|
4940 | | - u32 cause = t4_read_reg(adapter, PL_INT_CAUSE_A); |
---|
| 5028 | + /* There are rare cases where a PL_INT_CAUSE bit may end up getting |
---|
| 5029 | + * set when the corresponding PL_INT_ENABLE bit isn't set. It's |
---|
| 5030 | + * easiest just to mask that case here. |
---|
| 5031 | + */ |
---|
| 5032 | + u32 raw_cause = t4_read_reg(adapter, PL_INT_CAUSE_A); |
---|
| 5033 | + u32 enable = t4_read_reg(adapter, PL_INT_ENABLE_A); |
---|
| 5034 | + u32 cause = raw_cause & enable; |
---|
4941 | 5035 | |
---|
4942 | 5036 | if (!(cause & GLBL_INTR_MASK)) |
---|
4943 | 5037 | return 0; |
---|
.. | .. |
---|
4989 | 5083 | ulptx_intr_handler(adapter); |
---|
4990 | 5084 | |
---|
4991 | 5085 | /* Clear the interrupts just processed for which we are the master. */ |
---|
4992 | | - t4_write_reg(adapter, PL_INT_CAUSE_A, cause & GLBL_INTR_MASK); |
---|
| 5086 | + t4_write_reg(adapter, PL_INT_CAUSE_A, raw_cause & GLBL_INTR_MASK); |
---|
4993 | 5087 | (void)t4_read_reg(adapter, PL_INT_CAUSE_A); /* flush */ |
---|
4994 | 5088 | return 1; |
---|
4995 | 5089 | } |
---|
.. | .. |
---|
5212 | 5306 | |
---|
5213 | 5307 | static unsigned int t4_use_ldst(struct adapter *adap) |
---|
5214 | 5308 | { |
---|
5215 | | - return (adap->flags & FW_OK) && !adap->use_bd; |
---|
| 5309 | + return (adap->flags & CXGB4_FW_OK) && !adap->use_bd; |
---|
5216 | 5310 | } |
---|
5217 | 5311 | |
---|
5218 | 5312 | /** |
---|
.. | .. |
---|
5221 | 5315 | * @cmd: TP fw ldst address space type |
---|
5222 | 5316 | * @vals: where the indirect register values are stored/written |
---|
5223 | 5317 | * @nregs: how many indirect registers to read/write |
---|
5224 | | - * @start_idx: index of first indirect register to read/write |
---|
| 5318 | + * @start_index: index of first indirect register to read/write |
---|
5225 | 5319 | * @rw: Read (1) or Write (0) |
---|
5226 | 5320 | * @sleep_ok: if true we may sleep while awaiting command completion |
---|
5227 | 5321 | * |
---|
.. | .. |
---|
5875 | 5969 | { |
---|
5876 | 5970 | int i, ofst = idx * 4; |
---|
5877 | 5971 | u32 data_reg, mask_reg, cfg; |
---|
5878 | | - u32 multitrc = TRCMULTIFILTER_F; |
---|
5879 | 5972 | |
---|
5880 | 5973 | if (!enable) { |
---|
5881 | 5974 | t4_write_reg(adap, MPS_TRC_FILTER_MATCH_CTL_A_A + ofst, 0); |
---|
.. | .. |
---|
5895 | 5988 | * maximum packet capture size of 9600 bytes is recommended. |
---|
5896 | 5989 | * Also in this mode, only trace0 can be enabled and running. |
---|
5897 | 5990 | */ |
---|
5898 | | - multitrc = 0; |
---|
5899 | 5991 | if (tp->snap_len > 9600 || idx) |
---|
5900 | 5992 | return -EINVAL; |
---|
5901 | 5993 | } |
---|
.. | .. |
---|
6028 | 6120 | |
---|
6029 | 6121 | /** |
---|
6030 | 6122 | * compute_mps_bg_map - compute the MPS Buffer Group Map for a Port |
---|
6031 | | - * @adap: the adapter |
---|
| 6123 | + * @adapter: the adapter |
---|
6032 | 6124 | * @pidx: the port index |
---|
6033 | 6125 | * |
---|
6034 | 6126 | * Computes and returns a bitmap indicating which MPS buffer groups are |
---|
.. | .. |
---|
6103 | 6195 | * ( MPSBGMAP[Port 1] << 8 ) | |
---|
6104 | 6196 | * ( MPSBGMAP[Port 0] << 0 )) |
---|
6105 | 6197 | */ |
---|
6106 | | - if (adapter->flags & FW_OK) { |
---|
| 6198 | + if (adapter->flags & CXGB4_FW_OK) { |
---|
6107 | 6199 | u32 param, val; |
---|
6108 | 6200 | int ret; |
---|
6109 | 6201 | |
---|
.. | .. |
---|
6133 | 6225 | } |
---|
6134 | 6226 | |
---|
6135 | 6227 | /** |
---|
| 6228 | + * t4_get_tp_e2c_map - return the E2C channel map associated with a port |
---|
| 6229 | + * @adapter: the adapter |
---|
| 6230 | + * @pidx: the port index |
---|
| 6231 | + */ |
---|
| 6232 | +static unsigned int t4_get_tp_e2c_map(struct adapter *adapter, int pidx) |
---|
| 6233 | +{ |
---|
| 6234 | + unsigned int nports; |
---|
| 6235 | + u32 param, val = 0; |
---|
| 6236 | + int ret; |
---|
| 6237 | + |
---|
| 6238 | + nports = 1 << NUMPORTS_G(t4_read_reg(adapter, MPS_CMN_CTL_A)); |
---|
| 6239 | + if (pidx >= nports) { |
---|
| 6240 | + CH_WARN(adapter, "TP E2C Channel Port Index %d >= Nports %d\n", |
---|
| 6241 | + pidx, nports); |
---|
| 6242 | + return 0; |
---|
| 6243 | + } |
---|
| 6244 | + |
---|
| 6245 | + /* FW version >= 1.16.44.0 can determine E2C channel map using |
---|
| 6246 | + * FW_PARAMS_PARAM_DEV_TPCHMAP API. |
---|
| 6247 | + */ |
---|
| 6248 | + param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | |
---|
| 6249 | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_TPCHMAP)); |
---|
| 6250 | + ret = t4_query_params_ns(adapter, adapter->mbox, adapter->pf, |
---|
| 6251 | + 0, 1, ¶m, &val); |
---|
| 6252 | + if (!ret) |
---|
| 6253 | + return (val >> (8 * pidx)) & 0xff; |
---|
| 6254 | + |
---|
| 6255 | + return 0; |
---|
| 6256 | +} |
---|
| 6257 | + |
---|
| 6258 | +/** |
---|
6136 | 6259 | * t4_get_tp_ch_map - return TP ingress channels associated with a port |
---|
6137 | | - * @adapter: the adapter |
---|
| 6260 | + * @adap: the adapter |
---|
6138 | 6261 | * @pidx: the port index |
---|
6139 | 6262 | * |
---|
6140 | 6263 | * Returns a bitmap indicating which TP Ingress Channels are associated |
---|
.. | .. |
---|
6471 | 6594 | * @phy_addr: the PHY address |
---|
6472 | 6595 | * @mmd: the PHY MMD to access (0 for clause 22 PHYs) |
---|
6473 | 6596 | * @reg: the register to write |
---|
6474 | | - * @valp: value to write |
---|
| 6597 | + * @val: value to write |
---|
6475 | 6598 | * |
---|
6476 | 6599 | * Issues a FW command through the given mailbox to write a PHY register. |
---|
6477 | 6600 | */ |
---|
.. | .. |
---|
6497 | 6620 | |
---|
6498 | 6621 | /** |
---|
6499 | 6622 | * t4_sge_decode_idma_state - decode the idma state |
---|
6500 | | - * @adap: the adapter |
---|
| 6623 | + * @adapter: the adapter |
---|
6501 | 6624 | * @state: the state idma is stuck in |
---|
6502 | 6625 | */ |
---|
6503 | 6626 | void t4_sge_decode_idma_state(struct adapter *adapter, int state) |
---|
.. | .. |
---|
6664 | 6787 | * t4_sge_ctxt_flush - flush the SGE context cache |
---|
6665 | 6788 | * @adap: the adapter |
---|
6666 | 6789 | * @mbox: mailbox to use for the FW command |
---|
6667 | | - * @ctx_type: Egress or Ingress |
---|
| 6790 | + * @ctxt_type: Egress or Ingress |
---|
6668 | 6791 | * |
---|
6669 | 6792 | * Issues a FW command through the given mailbox to flush the |
---|
6670 | 6793 | * SGE context cache. |
---|
.. | .. |
---|
6686 | 6809 | c.u.idctxt.msg_ctxtflush = cpu_to_be32(FW_LDST_CMD_CTXTFLUSH_F); |
---|
6687 | 6810 | |
---|
6688 | 6811 | ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); |
---|
| 6812 | + return ret; |
---|
| 6813 | +} |
---|
| 6814 | + |
---|
| 6815 | +/** |
---|
| 6816 | + * t4_read_sge_dbqtimers - read SGE Doorbell Queue Timer values |
---|
| 6817 | + * @adap: the adapter |
---|
| 6818 | + * @ndbqtimers: size of the provided SGE Doorbell Queue Timer table |
---|
| 6819 | + * @dbqtimers: SGE Doorbell Queue Timer table |
---|
| 6820 | + * |
---|
| 6821 | + * Reads the SGE Doorbell Queue Timer values into the provided table. |
---|
| 6822 | + * Returns 0 on success (Firmware and Hardware support this feature), |
---|
| 6823 | + * an error on failure. |
---|
| 6824 | + */ |
---|
| 6825 | +int t4_read_sge_dbqtimers(struct adapter *adap, unsigned int ndbqtimers, |
---|
| 6826 | + u16 *dbqtimers) |
---|
| 6827 | +{ |
---|
| 6828 | + int ret, dbqtimerix; |
---|
| 6829 | + |
---|
| 6830 | + ret = 0; |
---|
| 6831 | + dbqtimerix = 0; |
---|
| 6832 | + while (dbqtimerix < ndbqtimers) { |
---|
| 6833 | + int nparams, param; |
---|
| 6834 | + u32 params[7], vals[7]; |
---|
| 6835 | + |
---|
| 6836 | + nparams = ndbqtimers - dbqtimerix; |
---|
| 6837 | + if (nparams > ARRAY_SIZE(params)) |
---|
| 6838 | + nparams = ARRAY_SIZE(params); |
---|
| 6839 | + |
---|
| 6840 | + for (param = 0; param < nparams; param++) |
---|
| 6841 | + params[param] = |
---|
| 6842 | + (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | |
---|
| 6843 | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_DBQ_TIMER) | |
---|
| 6844 | + FW_PARAMS_PARAM_Y_V(dbqtimerix + param)); |
---|
| 6845 | + ret = t4_query_params(adap, adap->mbox, adap->pf, 0, |
---|
| 6846 | + nparams, params, vals); |
---|
| 6847 | + if (ret) |
---|
| 6848 | + break; |
---|
| 6849 | + |
---|
| 6850 | + for (param = 0; param < nparams; param++) |
---|
| 6851 | + dbqtimers[dbqtimerix++] = vals[param]; |
---|
| 6852 | + } |
---|
6689 | 6853 | return ret; |
---|
6690 | 6854 | } |
---|
6691 | 6855 | |
---|
.. | .. |
---|
6777 | 6941 | waiting -= 50; |
---|
6778 | 6942 | |
---|
6779 | 6943 | /* |
---|
6780 | | - * If neither Error nor Initialialized are indicated |
---|
6781 | | - * by the firmware keep waiting till we exaust our |
---|
| 6944 | + * If neither Error nor Initialized are indicated |
---|
| 6945 | + * by the firmware keep waiting till we exhaust our |
---|
6782 | 6946 | * timeout ... and then retry if we haven't exhausted |
---|
6783 | 6947 | * our retries ... |
---|
6784 | 6948 | */ |
---|
.. | .. |
---|
6933 | 7097 | /** |
---|
6934 | 7098 | * t4_fw_restart - restart the firmware by taking the uP out of RESET |
---|
6935 | 7099 | * @adap: the adapter |
---|
| 7100 | + * @mbox: mailbox to use for the FW command |
---|
6936 | 7101 | * @reset: if we want to do a RESET to restart things |
---|
6937 | 7102 | * |
---|
6938 | 7103 | * Restart firmware previously halted by t4_fw_halt(). On successful |
---|
.. | .. |
---|
7023 | 7188 | if (!t4_fw_matches_chip(adap, fw_hdr)) |
---|
7024 | 7189 | return -EINVAL; |
---|
7025 | 7190 | |
---|
7026 | | - /* Disable FW_OK flag so that mbox commands with FW_OK flag set |
---|
7027 | | - * wont be sent when we are flashing FW. |
---|
| 7191 | + /* Disable CXGB4_FW_OK flag so that mbox commands with CXGB4_FW_OK flag |
---|
| 7192 | + * set wont be sent when we are flashing FW. |
---|
7028 | 7193 | */ |
---|
7029 | | - adap->flags &= ~FW_OK; |
---|
| 7194 | + adap->flags &= ~CXGB4_FW_OK; |
---|
7030 | 7195 | |
---|
7031 | 7196 | ret = t4_fw_halt(adap, mbox, force); |
---|
7032 | 7197 | if (ret < 0 && !force) |
---|
.. | .. |
---|
7065 | 7230 | */ |
---|
7066 | 7231 | (void)t4_init_devlog_params(adap); |
---|
7067 | 7232 | out: |
---|
7068 | | - adap->flags |= FW_OK; |
---|
| 7233 | + adap->flags |= CXGB4_FW_OK; |
---|
7069 | 7234 | return ret; |
---|
7070 | 7235 | } |
---|
7071 | 7236 | |
---|
.. | .. |
---|
7090 | 7255 | * separately. The actual Ingress Packet Data alignment boundary |
---|
7091 | 7256 | * within Packed Buffer Mode is the maximum of these two |
---|
7092 | 7257 | * specifications. (Note that it makes no real practical sense to |
---|
7093 | | - * have the Pading Boudary be larger than the Packing Boundary but you |
---|
| 7258 | + * have the Padding Boundary be larger than the Packing Boundary but you |
---|
7094 | 7259 | * could set the chip up that way and, in fact, legacy T4 code would |
---|
7095 | 7260 | * end doing this because it would initialize the Padding Boundary and |
---|
7096 | 7261 | * leave the Packing Boundary initialized to 0 (16 bytes).) |
---|
.. | .. |
---|
7161 | 7326 | } else { |
---|
7162 | 7327 | unsigned int pack_align; |
---|
7163 | 7328 | unsigned int ingpad, ingpack; |
---|
7164 | | - unsigned int pcie_cap; |
---|
7165 | 7329 | |
---|
7166 | 7330 | /* T5 introduced the separation of the Free List Padding and |
---|
7167 | 7331 | * Packing Boundaries. Thus, we can select a smaller Padding |
---|
.. | .. |
---|
7186 | 7350 | * multiple of the Maximum Payload Size. |
---|
7187 | 7351 | */ |
---|
7188 | 7352 | pack_align = fl_align; |
---|
7189 | | - pcie_cap = pci_find_capability(adap->pdev, PCI_CAP_ID_EXP); |
---|
7190 | | - if (pcie_cap) { |
---|
| 7353 | + if (pci_is_pcie(adap->pdev)) { |
---|
7191 | 7354 | unsigned int mps, mps_log; |
---|
7192 | 7355 | u16 devctl; |
---|
7193 | 7356 | |
---|
.. | .. |
---|
7195 | 7358 | * [bits 7:5] encodes sizes as powers of 2 starting at |
---|
7196 | 7359 | * 128 bytes. |
---|
7197 | 7360 | */ |
---|
7198 | | - pci_read_config_word(adap->pdev, |
---|
7199 | | - pcie_cap + PCI_EXP_DEVCTL, |
---|
7200 | | - &devctl); |
---|
| 7361 | + pcie_capability_read_word(adap->pdev, PCI_EXP_DEVCTL, |
---|
| 7362 | + &devctl); |
---|
7201 | 7363 | mps_log = ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5) + 7; |
---|
7202 | 7364 | mps = 1 << mps_log; |
---|
7203 | 7365 | if (mps > pack_align) |
---|
.. | .. |
---|
7474 | 7636 | * @nmac: number of MAC addresses needed (1 to 5) |
---|
7475 | 7637 | * @mac: the MAC addresses of the VI |
---|
7476 | 7638 | * @rss_size: size of RSS table slice associated with this VI |
---|
| 7639 | + * @vivld: the destination to store the VI Valid value. |
---|
| 7640 | + * @vin: the destination to store the VIN value. |
---|
7477 | 7641 | * |
---|
7478 | 7642 | * Allocates a virtual interface for the given physical port. If @mac is |
---|
7479 | 7643 | * not %NULL it contains the MAC addresses of the VI as assigned by FW. |
---|
.. | .. |
---|
7483 | 7647 | */ |
---|
7484 | 7648 | int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port, |
---|
7485 | 7649 | unsigned int pf, unsigned int vf, unsigned int nmac, u8 *mac, |
---|
7486 | | - unsigned int *rss_size) |
---|
| 7650 | + unsigned int *rss_size, u8 *vivld, u8 *vin) |
---|
7487 | 7651 | { |
---|
7488 | 7652 | int ret; |
---|
7489 | 7653 | struct fw_vi_cmd c; |
---|
.. | .. |
---|
7505 | 7669 | switch (nmac) { |
---|
7506 | 7670 | case 5: |
---|
7507 | 7671 | memcpy(mac + 24, c.nmac3, sizeof(c.nmac3)); |
---|
7508 | | - /* Fall through */ |
---|
| 7672 | + fallthrough; |
---|
7509 | 7673 | case 4: |
---|
7510 | 7674 | memcpy(mac + 18, c.nmac2, sizeof(c.nmac2)); |
---|
7511 | | - /* Fall through */ |
---|
| 7675 | + fallthrough; |
---|
7512 | 7676 | case 3: |
---|
7513 | 7677 | memcpy(mac + 12, c.nmac1, sizeof(c.nmac1)); |
---|
7514 | | - /* Fall through */ |
---|
| 7678 | + fallthrough; |
---|
7515 | 7679 | case 2: |
---|
7516 | 7680 | memcpy(mac + 6, c.nmac0, sizeof(c.nmac0)); |
---|
7517 | 7681 | } |
---|
7518 | 7682 | } |
---|
7519 | 7683 | if (rss_size) |
---|
7520 | 7684 | *rss_size = FW_VI_CMD_RSSSIZE_G(be16_to_cpu(c.rsssize_pkd)); |
---|
| 7685 | + |
---|
| 7686 | + if (vivld) |
---|
| 7687 | + *vivld = FW_VI_CMD_VFVLD_G(be32_to_cpu(c.alloc_to_len16)); |
---|
| 7688 | + |
---|
| 7689 | + if (vin) |
---|
| 7690 | + *vin = FW_VI_CMD_VIN_G(be32_to_cpu(c.alloc_to_len16)); |
---|
| 7691 | + |
---|
7521 | 7692 | return FW_VI_CMD_VIID_G(be16_to_cpu(c.type_viid)); |
---|
7522 | 7693 | } |
---|
7523 | 7694 | |
---|
.. | .. |
---|
7553 | 7724 | * @adap: the adapter |
---|
7554 | 7725 | * @mbox: mailbox to use for the FW command |
---|
7555 | 7726 | * @viid: the VI id |
---|
| 7727 | + * @viid_mirror: the mirror VI id |
---|
7556 | 7728 | * @mtu: the new MTU or -1 |
---|
7557 | 7729 | * @promisc: 1 to enable promiscuous mode, 0 to disable it, -1 no change |
---|
7558 | 7730 | * @all_multi: 1 to enable all-multi mode, 0 to disable it, -1 no change |
---|
.. | .. |
---|
7563 | 7735 | * Sets Rx properties of a virtual interface. |
---|
7564 | 7736 | */ |
---|
7565 | 7737 | int t4_set_rxmode(struct adapter *adap, unsigned int mbox, unsigned int viid, |
---|
7566 | | - int mtu, int promisc, int all_multi, int bcast, int vlanex, |
---|
7567 | | - bool sleep_ok) |
---|
| 7738 | + unsigned int viid_mirror, int mtu, int promisc, int all_multi, |
---|
| 7739 | + int bcast, int vlanex, bool sleep_ok) |
---|
7568 | 7740 | { |
---|
7569 | | - struct fw_vi_rxmode_cmd c; |
---|
| 7741 | + struct fw_vi_rxmode_cmd c, c_mirror; |
---|
| 7742 | + int ret; |
---|
7570 | 7743 | |
---|
7571 | 7744 | /* convert to FW values */ |
---|
7572 | 7745 | if (mtu < 0) |
---|
.. | .. |
---|
7591 | 7764 | FW_VI_RXMODE_CMD_ALLMULTIEN_V(all_multi) | |
---|
7592 | 7765 | FW_VI_RXMODE_CMD_BROADCASTEN_V(bcast) | |
---|
7593 | 7766 | FW_VI_RXMODE_CMD_VLANEXEN_V(vlanex)); |
---|
7594 | | - return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok); |
---|
| 7767 | + |
---|
| 7768 | + if (viid_mirror) { |
---|
| 7769 | + memcpy(&c_mirror, &c, sizeof(c_mirror)); |
---|
| 7770 | + c_mirror.op_to_viid = |
---|
| 7771 | + cpu_to_be32(FW_CMD_OP_V(FW_VI_RXMODE_CMD) | |
---|
| 7772 | + FW_CMD_REQUEST_F | FW_CMD_WRITE_F | |
---|
| 7773 | + FW_VI_RXMODE_CMD_VIID_V(viid_mirror)); |
---|
| 7774 | + } |
---|
| 7775 | + |
---|
| 7776 | + ret = t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok); |
---|
| 7777 | + if (ret) |
---|
| 7778 | + return ret; |
---|
| 7779 | + |
---|
| 7780 | + if (viid_mirror) |
---|
| 7781 | + ret = t4_wr_mbox_meat(adap, mbox, &c_mirror, sizeof(c_mirror), |
---|
| 7782 | + NULL, sleep_ok); |
---|
| 7783 | + |
---|
| 7784 | + return ret; |
---|
7595 | 7785 | } |
---|
7596 | 7786 | |
---|
7597 | 7787 | /** |
---|
.. | .. |
---|
7685 | 7875 | * t4_alloc_encap_mac_filt - Adds a mac entry in mps tcam with VNI support |
---|
7686 | 7876 | * @adap: the adapter |
---|
7687 | 7877 | * @viid: the VI id |
---|
7688 | | - * @mac: the MAC address |
---|
| 7878 | + * @addr: the MAC address |
---|
7689 | 7879 | * @mask: the mask |
---|
7690 | 7880 | * @vni: the VNI id for the tunnel protocol |
---|
7691 | 7881 | * @vni_mask: mask for the VNI id |
---|
.. | .. |
---|
7734 | 7924 | * t4_alloc_raw_mac_filt - Adds a mac entry in mps tcam |
---|
7735 | 7925 | * @adap: the adapter |
---|
7736 | 7926 | * @viid: the VI id |
---|
7737 | | - * @mac: the MAC address |
---|
| 7927 | + * @addr: the MAC address |
---|
7738 | 7928 | * @mask: the mask |
---|
7739 | 7929 | * @idx: index at which to add this entry |
---|
7740 | | - * @port_id: the port index |
---|
7741 | 7930 | * @lookup_type: MAC address for inner (1) or outer (0) header |
---|
| 7931 | + * @port_id: the port index |
---|
7742 | 7932 | * @sleep_ok: call is allowed to sleep |
---|
7743 | 7933 | * |
---|
7744 | 7934 | * Adds the mac entry at the specified index using raw mac interface. |
---|
.. | .. |
---|
7963 | 8153 | * @idx: index of existing filter for old value of MAC address, or -1 |
---|
7964 | 8154 | * @addr: the new MAC address value |
---|
7965 | 8155 | * @persist: whether a new MAC allocation should be persistent |
---|
7966 | | - * @add_smt: if true also add the address to the HW SMT |
---|
| 8156 | + * @smt_idx: the destination to store the new SMT index. |
---|
7967 | 8157 | * |
---|
7968 | 8158 | * Modifies an exact-match filter and sets it to the new MAC address. |
---|
7969 | 8159 | * Note that in general it is not possible to modify the value of a given |
---|
.. | .. |
---|
7975 | 8165 | * MAC value. |
---|
7976 | 8166 | */ |
---|
7977 | 8167 | int t4_change_mac(struct adapter *adap, unsigned int mbox, unsigned int viid, |
---|
7978 | | - int idx, const u8 *addr, bool persist, bool add_smt) |
---|
| 8168 | + int idx, const u8 *addr, bool persist, u8 *smt_idx) |
---|
7979 | 8169 | { |
---|
7980 | 8170 | int ret, mode; |
---|
7981 | 8171 | struct fw_vi_mac_cmd c; |
---|
.. | .. |
---|
7984 | 8174 | |
---|
7985 | 8175 | if (idx < 0) /* new allocation */ |
---|
7986 | 8176 | idx = persist ? FW_VI_MAC_ADD_PERSIST_MAC : FW_VI_MAC_ADD_MAC; |
---|
7987 | | - mode = add_smt ? FW_VI_MAC_SMT_AND_MPSTCAM : FW_VI_MAC_MPS_TCAM_ENTRY; |
---|
| 8177 | + mode = smt_idx ? FW_VI_MAC_SMT_AND_MPSTCAM : FW_VI_MAC_MPS_TCAM_ENTRY; |
---|
7988 | 8178 | |
---|
7989 | 8179 | memset(&c, 0, sizeof(c)); |
---|
7990 | 8180 | c.op_to_viid = cpu_to_be32(FW_CMD_OP_V(FW_VI_MAC_CMD) | |
---|
.. | .. |
---|
8001 | 8191 | ret = FW_VI_MAC_CMD_IDX_G(be16_to_cpu(p->valid_to_idx)); |
---|
8002 | 8192 | if (ret >= max_mac_addr) |
---|
8003 | 8193 | ret = -ENOMEM; |
---|
| 8194 | + if (smt_idx) { |
---|
| 8195 | + if (adap->params.viid_smt_extn_support) { |
---|
| 8196 | + *smt_idx = FW_VI_MAC_CMD_SMTID_G |
---|
| 8197 | + (be32_to_cpu(c.op_to_viid)); |
---|
| 8198 | + } else { |
---|
| 8199 | + /* In T4/T5, SMT contains 256 SMAC entries |
---|
| 8200 | + * organized in 128 rows of 2 entries each. |
---|
| 8201 | + * In T6, SMT contains 256 SMAC entries in |
---|
| 8202 | + * 256 rows. |
---|
| 8203 | + */ |
---|
| 8204 | + if (CHELSIO_CHIP_VERSION(adap->params.chip) <= |
---|
| 8205 | + CHELSIO_T5) |
---|
| 8206 | + *smt_idx = (viid & FW_VIID_VIN_M) << 1; |
---|
| 8207 | + else |
---|
| 8208 | + *smt_idx = (viid & FW_VIID_VIN_M); |
---|
| 8209 | + } |
---|
| 8210 | + } |
---|
8004 | 8211 | } |
---|
8005 | 8212 | return ret; |
---|
8006 | 8213 | } |
---|
.. | .. |
---|
8268 | 8475 | |
---|
8269 | 8476 | /** |
---|
8270 | 8477 | * t4_link_down_rc_str - return a string for a Link Down Reason Code |
---|
8271 | | - * @adap: the adapter |
---|
8272 | 8478 | * @link_down_rc: Link Down Reason Code |
---|
8273 | 8479 | * |
---|
8274 | 8480 | * Returns a string representation of the Link Down Reason Code. |
---|
.. | .. |
---|
8292 | 8498 | return reason[link_down_rc]; |
---|
8293 | 8499 | } |
---|
8294 | 8500 | |
---|
8295 | | -/** |
---|
8296 | | - * Return the highest speed set in the port capabilities, in Mb/s. |
---|
8297 | | - */ |
---|
| 8501 | +/* Return the highest speed set in the port capabilities, in Mb/s. */ |
---|
8298 | 8502 | static unsigned int fwcap_to_speed(fw_port_cap32_t caps) |
---|
8299 | 8503 | { |
---|
8300 | 8504 | #define TEST_SPEED_RETURN(__caps_speed, __speed) \ |
---|
.. | .. |
---|
8394 | 8598 | void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl) |
---|
8395 | 8599 | { |
---|
8396 | 8600 | const struct fw_port_cmd *cmd = (const void *)rpl; |
---|
8397 | | - int action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16)); |
---|
8398 | | - struct adapter *adapter = pi->adapter; |
---|
8399 | | - struct link_config *lc = &pi->link_cfg; |
---|
8400 | | - int link_ok, linkdnrc; |
---|
8401 | | - enum fw_port_type port_type; |
---|
8402 | | - enum fw_port_module_type mod_type; |
---|
8403 | | - unsigned int speed, fc, fec; |
---|
8404 | 8601 | fw_port_cap32_t pcaps, acaps, lpacaps, linkattr; |
---|
| 8602 | + struct link_config *lc = &pi->link_cfg; |
---|
| 8603 | + struct adapter *adapter = pi->adapter; |
---|
| 8604 | + unsigned int speed, fc, fec, adv_fc; |
---|
| 8605 | + enum fw_port_module_type mod_type; |
---|
| 8606 | + int action, link_ok, linkdnrc; |
---|
| 8607 | + enum fw_port_type port_type; |
---|
8405 | 8608 | |
---|
8406 | 8609 | /* Extract the various fields from the Port Information message. |
---|
8407 | 8610 | */ |
---|
| 8611 | + action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16)); |
---|
8408 | 8612 | switch (action) { |
---|
8409 | 8613 | case FW_PORT_ACTION_GET_PORT_INFO: { |
---|
8410 | 8614 | u32 lstatus = be32_to_cpu(cmd->u.info.lstatus_to_modtype); |
---|
.. | .. |
---|
8442 | 8646 | } |
---|
8443 | 8647 | |
---|
8444 | 8648 | fec = fwcap_to_cc_fec(acaps); |
---|
| 8649 | + adv_fc = fwcap_to_cc_pause(acaps); |
---|
8445 | 8650 | fc = fwcap_to_cc_pause(linkattr); |
---|
8446 | 8651 | speed = fwcap_to_speed(linkattr); |
---|
8447 | 8652 | |
---|
| 8653 | + /* Reset state for communicating new Transceiver Module status and |
---|
| 8654 | + * whether the OS-dependent layer wants us to redo the current |
---|
| 8655 | + * "sticky" L1 Configure Link Parameters. |
---|
| 8656 | + */ |
---|
8448 | 8657 | lc->new_module = false; |
---|
8449 | 8658 | lc->redo_l1cfg = false; |
---|
8450 | 8659 | |
---|
.. | .. |
---|
8481 | 8690 | */ |
---|
8482 | 8691 | pi->port_type = port_type; |
---|
8483 | 8692 | |
---|
| 8693 | + /* Record new Module Type information. |
---|
| 8694 | + */ |
---|
8484 | 8695 | pi->mod_type = mod_type; |
---|
8485 | 8696 | |
---|
| 8697 | + /* Let the OS-dependent layer know if we have a new |
---|
| 8698 | + * Transceiver Module inserted. |
---|
| 8699 | + */ |
---|
8486 | 8700 | lc->new_module = t4_is_inserted_mod_type(mod_type); |
---|
| 8701 | + |
---|
8487 | 8702 | t4_os_portmod_changed(adapter, pi->port_id); |
---|
8488 | 8703 | } |
---|
8489 | 8704 | |
---|
8490 | 8705 | if (link_ok != lc->link_ok || speed != lc->speed || |
---|
8491 | | - fc != lc->fc || fec != lc->fec) { /* something changed */ |
---|
| 8706 | + fc != lc->fc || adv_fc != lc->advertised_fc || |
---|
| 8707 | + fec != lc->fec) { |
---|
| 8708 | + /* something changed */ |
---|
8492 | 8709 | if (!link_ok && lc->link_ok) { |
---|
8493 | 8710 | lc->link_down_rc = linkdnrc; |
---|
8494 | | - dev_warn(adapter->pdev_dev, "Port %d link down, reason: %s\n", |
---|
8495 | | - pi->tx_chan, t4_link_down_rc_str(linkdnrc)); |
---|
| 8711 | + dev_warn_ratelimited(adapter->pdev_dev, |
---|
| 8712 | + "Port %d link down, reason: %s\n", |
---|
| 8713 | + pi->tx_chan, |
---|
| 8714 | + t4_link_down_rc_str(linkdnrc)); |
---|
8496 | 8715 | } |
---|
8497 | 8716 | lc->link_ok = link_ok; |
---|
8498 | 8717 | lc->speed = speed; |
---|
| 8718 | + lc->advertised_fc = adv_fc; |
---|
8499 | 8719 | lc->fc = fc; |
---|
8500 | 8720 | lc->fec = fec; |
---|
8501 | 8721 | |
---|
8502 | 8722 | lc->lpacaps = lpacaps; |
---|
8503 | 8723 | lc->acaps = acaps & ADVERT_MASK; |
---|
8504 | 8724 | |
---|
| 8725 | + /* If we're not physically capable of Auto-Negotiation, note |
---|
| 8726 | + * this as Auto-Negotiation disabled. Otherwise, we track |
---|
| 8727 | + * what Auto-Negotiation settings we have. Note parallel |
---|
| 8728 | + * structure in t4_link_l1cfg_core() and init_link_config(). |
---|
| 8729 | + */ |
---|
8505 | 8730 | if (!(lc->acaps & FW_PORT_CAP32_ANEG)) { |
---|
8506 | 8731 | lc->autoneg = AUTONEG_DISABLE; |
---|
8507 | 8732 | } else if (lc->acaps & FW_PORT_CAP32_ANEG) { |
---|
.. | .. |
---|
8519 | 8744 | t4_os_link_changed(adapter, pi->port_id, link_ok); |
---|
8520 | 8745 | } |
---|
8521 | 8746 | |
---|
| 8747 | + /* If we have a new Transceiver Module and the OS-dependent code has |
---|
| 8748 | + * told us that it wants us to redo whatever "sticky" L1 Configuration |
---|
| 8749 | + * Link Parameters are set, do that now. |
---|
| 8750 | + */ |
---|
8522 | 8751 | if (lc->new_module && lc->redo_l1cfg) { |
---|
8523 | 8752 | struct link_config old_lc; |
---|
8524 | 8753 | int ret; |
---|
.. | .. |
---|
8587 | 8816 | unsigned int *speedp, unsigned int *mtup) |
---|
8588 | 8817 | { |
---|
8589 | 8818 | unsigned int fw_caps = pi->adapter->params.fw_caps_support; |
---|
| 8819 | + unsigned int action, link_ok, mtu; |
---|
8590 | 8820 | struct fw_port_cmd port_cmd; |
---|
8591 | | - unsigned int action, link_ok, speed, mtu; |
---|
8592 | 8821 | fw_port_cap32_t linkattr; |
---|
8593 | 8822 | int ret; |
---|
8594 | 8823 | |
---|
.. | .. |
---|
8622 | 8851 | mtu = FW_PORT_CMD_MTU32_G( |
---|
8623 | 8852 | be32_to_cpu(port_cmd.u.info32.auxlinfo32_mtu32)); |
---|
8624 | 8853 | } |
---|
8625 | | - speed = fwcap_to_speed(linkattr); |
---|
8626 | 8854 | |
---|
8627 | | - *link_okp = link_ok; |
---|
8628 | | - *speedp = fwcap_to_speed(linkattr); |
---|
8629 | | - *mtup = mtu; |
---|
| 8855 | + if (link_okp) |
---|
| 8856 | + *link_okp = link_ok; |
---|
| 8857 | + if (speedp) |
---|
| 8858 | + *speedp = fwcap_to_speed(linkattr); |
---|
| 8859 | + if (mtup) |
---|
| 8860 | + *mtup = mtu; |
---|
8630 | 8861 | |
---|
8631 | 8862 | return 0; |
---|
8632 | 8863 | } |
---|
.. | .. |
---|
8784 | 9015 | goto found; |
---|
8785 | 9016 | } |
---|
8786 | 9017 | |
---|
8787 | | - /* Decode Flash part size. The code below looks repetative with |
---|
| 9018 | + /* Decode Flash part size. The code below looks repetitive with |
---|
8788 | 9019 | * common encodings, but that's not guaranteed in the JEDEC |
---|
8789 | | - * specification for the Read JADEC ID command. The only thing that |
---|
8790 | | - * we're guaranteed by the JADEC specification is where the |
---|
| 9020 | + * specification for the Read JEDEC ID command. The only thing that |
---|
| 9021 | + * we're guaranteed by the JEDEC specification is where the |
---|
8791 | 9022 | * Manufacturer ID is in the returned result. After that each |
---|
8792 | 9023 | * Manufacturer ~could~ encode things completely differently. |
---|
8793 | 9024 | * Note, all Flash parts must have 64KB sectors. |
---|
.. | .. |
---|
8903 | 9134 | /** |
---|
8904 | 9135 | * t4_prep_adapter - prepare SW and HW for operation |
---|
8905 | 9136 | * @adapter: the adapter |
---|
8906 | | - * @reset: if true perform a HW reset |
---|
8907 | 9137 | * |
---|
8908 | 9138 | * Initialize adapter SW state for the various HW modules, set initial |
---|
8909 | 9139 | * values for some adapter tunables, take PHYs out of reset, and |
---|
.. | .. |
---|
9128 | 9358 | struct fw_devlog_cmd devlog_cmd; |
---|
9129 | 9359 | int ret; |
---|
9130 | 9360 | |
---|
9131 | | - /* If we're dealing with newer firmware, the Device Log Paramerters |
---|
| 9361 | + /* If we're dealing with newer firmware, the Device Log Parameters |
---|
9132 | 9362 | * are stored in a designated register which allows us to access the |
---|
9133 | 9363 | * Device Log even if we can't talk to the firmware. |
---|
9134 | 9364 | */ |
---|
.. | .. |
---|
9207 | 9437 | */ |
---|
9208 | 9438 | int t4_init_tp_params(struct adapter *adap, bool sleep_ok) |
---|
9209 | 9439 | { |
---|
9210 | | - int chan; |
---|
9211 | | - u32 v; |
---|
| 9440 | + u32 param, val, v; |
---|
| 9441 | + int chan, ret; |
---|
| 9442 | + |
---|
9212 | 9443 | |
---|
9213 | 9444 | v = t4_read_reg(adap, TP_TIMER_RESOLUTION_A); |
---|
9214 | 9445 | adap->params.tp.tre = TIMERRESOLUTION_G(v); |
---|
.. | .. |
---|
9218 | 9449 | for (chan = 0; chan < NCHAN; chan++) |
---|
9219 | 9450 | adap->params.tp.tx_modq[chan] = chan; |
---|
9220 | 9451 | |
---|
9221 | | - /* Cache the adapter's Compressed Filter Mode and global Incress |
---|
| 9452 | + /* Cache the adapter's Compressed Filter Mode/Mask and global Ingress |
---|
9222 | 9453 | * Configuration. |
---|
9223 | 9454 | */ |
---|
9224 | | - t4_tp_pio_read(adap, &adap->params.tp.vlan_pri_map, 1, |
---|
9225 | | - TP_VLAN_PRI_MAP_A, sleep_ok); |
---|
| 9455 | + param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | |
---|
| 9456 | + FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_FILTER) | |
---|
| 9457 | + FW_PARAMS_PARAM_Y_V(FW_PARAM_DEV_FILTER_MODE_MASK)); |
---|
| 9458 | + |
---|
| 9459 | + /* Read current value */ |
---|
| 9460 | + ret = t4_query_params(adap, adap->mbox, adap->pf, 0, 1, |
---|
| 9461 | + ¶m, &val); |
---|
| 9462 | + if (ret == 0) { |
---|
| 9463 | + dev_info(adap->pdev_dev, |
---|
| 9464 | + "Current filter mode/mask 0x%x:0x%x\n", |
---|
| 9465 | + FW_PARAMS_PARAM_FILTER_MODE_G(val), |
---|
| 9466 | + FW_PARAMS_PARAM_FILTER_MASK_G(val)); |
---|
| 9467 | + adap->params.tp.vlan_pri_map = |
---|
| 9468 | + FW_PARAMS_PARAM_FILTER_MODE_G(val); |
---|
| 9469 | + adap->params.tp.filter_mask = |
---|
| 9470 | + FW_PARAMS_PARAM_FILTER_MASK_G(val); |
---|
| 9471 | + } else { |
---|
| 9472 | + dev_info(adap->pdev_dev, |
---|
| 9473 | + "Failed to read filter mode/mask via fw api, using indirect-reg-read\n"); |
---|
| 9474 | + |
---|
| 9475 | + /* Incase of older-fw (which doesn't expose the api |
---|
| 9476 | + * FW_PARAM_DEV_FILTER_MODE_MASK) and newer-driver (which uses |
---|
| 9477 | + * the fw api) combination, fall-back to older method of reading |
---|
| 9478 | + * the filter mode from indirect-register |
---|
| 9479 | + */ |
---|
| 9480 | + t4_tp_pio_read(adap, &adap->params.tp.vlan_pri_map, 1, |
---|
| 9481 | + TP_VLAN_PRI_MAP_A, sleep_ok); |
---|
| 9482 | + |
---|
| 9483 | + /* With the older-fw and newer-driver combination we might run |
---|
| 9484 | + * into an issue when user wants to use hash filter region but |
---|
| 9485 | + * the filter_mask is zero, in this case filter_mask validation |
---|
| 9486 | + * is tough. To avoid that we set the filter_mask same as filter |
---|
| 9487 | + * mode, which will behave exactly as the older way of ignoring |
---|
| 9488 | + * the filter mask validation. |
---|
| 9489 | + */ |
---|
| 9490 | + adap->params.tp.filter_mask = adap->params.tp.vlan_pri_map; |
---|
| 9491 | + } |
---|
| 9492 | + |
---|
9226 | 9493 | t4_tp_pio_read(adap, &adap->params.tp.ingress_config, 1, |
---|
9227 | 9494 | TP_INGRESS_CONFIG_A, sleep_ok); |
---|
9228 | 9495 | |
---|
.. | .. |
---|
9369 | 9636 | enum fw_port_type port_type; |
---|
9370 | 9637 | int mdio_addr; |
---|
9371 | 9638 | fw_port_cap32_t pcaps, acaps; |
---|
| 9639 | + u8 vivld = 0, vin = 0; |
---|
9372 | 9640 | int ret; |
---|
9373 | 9641 | |
---|
9374 | 9642 | /* If we haven't yet determined whether we're talking to Firmware |
---|
.. | .. |
---|
9423 | 9691 | acaps = be32_to_cpu(cmd.u.info32.acaps32); |
---|
9424 | 9692 | } |
---|
9425 | 9693 | |
---|
9426 | | - ret = t4_alloc_vi(pi->adapter, mbox, port, pf, vf, 1, mac, &rss_size); |
---|
| 9694 | + ret = t4_alloc_vi(pi->adapter, mbox, port, pf, vf, 1, mac, &rss_size, |
---|
| 9695 | + &vivld, &vin); |
---|
9427 | 9696 | if (ret < 0) |
---|
9428 | 9697 | return ret; |
---|
9429 | 9698 | |
---|
.. | .. |
---|
9431 | 9700 | pi->tx_chan = port; |
---|
9432 | 9701 | pi->lport = port; |
---|
9433 | 9702 | pi->rss_size = rss_size; |
---|
| 9703 | + pi->rx_cchan = t4_get_tp_e2c_map(pi->adapter, port); |
---|
| 9704 | + |
---|
| 9705 | + /* If fw supports returning the VIN as part of FW_VI_CMD, |
---|
| 9706 | + * save the returned values. |
---|
| 9707 | + */ |
---|
| 9708 | + if (adapter->params.viid_smt_extn_support) { |
---|
| 9709 | + pi->vivld = vivld; |
---|
| 9710 | + pi->vin = vin; |
---|
| 9711 | + } else { |
---|
| 9712 | + /* Retrieve the values from VIID */ |
---|
| 9713 | + pi->vivld = FW_VIID_VIVLD_G(pi->viid); |
---|
| 9714 | + pi->vin = FW_VIID_VIN_G(pi->viid); |
---|
| 9715 | + } |
---|
9434 | 9716 | |
---|
9435 | 9717 | pi->port_type = port_type; |
---|
9436 | 9718 | pi->mdio_addr = mdio_addr; |
---|
.. | .. |
---|
9458 | 9740 | memcpy(adap->port[i]->dev_addr, addr, ETH_ALEN); |
---|
9459 | 9741 | j++; |
---|
9460 | 9742 | } |
---|
| 9743 | + return 0; |
---|
| 9744 | +} |
---|
| 9745 | + |
---|
| 9746 | +int t4_init_port_mirror(struct port_info *pi, u8 mbox, u8 port, u8 pf, u8 vf, |
---|
| 9747 | + u16 *mirror_viid) |
---|
| 9748 | +{ |
---|
| 9749 | + int ret; |
---|
| 9750 | + |
---|
| 9751 | + ret = t4_alloc_vi(pi->adapter, mbox, port, pf, vf, 1, NULL, NULL, |
---|
| 9752 | + NULL, NULL); |
---|
| 9753 | + if (ret < 0) |
---|
| 9754 | + return ret; |
---|
| 9755 | + |
---|
| 9756 | + if (mirror_viid) |
---|
| 9757 | + *mirror_viid = ret; |
---|
| 9758 | + |
---|
9461 | 9759 | return 0; |
---|
9462 | 9760 | } |
---|
9463 | 9761 | |
---|
.. | .. |
---|
9927 | 10225 | n = size - i; |
---|
9928 | 10226 | else |
---|
9929 | 10227 | n = SF_PAGE_SIZE; |
---|
9930 | | - ret = t4_write_flash(adap, addr, n, cfg_data); |
---|
| 10228 | + ret = t4_write_flash(adap, addr, n, cfg_data, true); |
---|
9931 | 10229 | if (ret) |
---|
9932 | 10230 | goto out; |
---|
9933 | 10231 | |
---|
.. | .. |
---|
10102 | 10400 | return ret; |
---|
10103 | 10401 | } |
---|
10104 | 10402 | |
---|
10105 | | -int t4_sched_params(struct adapter *adapter, int type, int level, int mode, |
---|
10106 | | - int rateunit, int ratemode, int channel, int class, |
---|
10107 | | - int minrate, int maxrate, int weight, int pktsize) |
---|
| 10403 | +int t4_sched_params(struct adapter *adapter, u8 type, u8 level, u8 mode, |
---|
| 10404 | + u8 rateunit, u8 ratemode, u8 channel, u8 class, |
---|
| 10405 | + u32 minrate, u32 maxrate, u16 weight, u16 pktsize, |
---|
| 10406 | + u16 burstsize) |
---|
10108 | 10407 | { |
---|
10109 | 10408 | struct fw_sched_cmd cmd; |
---|
10110 | 10409 | |
---|
.. | .. |
---|
10126 | 10425 | cmd.u.params.max = cpu_to_be32(maxrate); |
---|
10127 | 10426 | cmd.u.params.weight = cpu_to_be16(weight); |
---|
10128 | 10427 | cmd.u.params.pktsize = cpu_to_be16(pktsize); |
---|
| 10428 | + cmd.u.params.burstsize = cpu_to_be16(burstsize); |
---|
10129 | 10429 | |
---|
10130 | 10430 | return t4_wr_mbox_meat(adapter, adapter->mbox, &cmd, sizeof(cmd), |
---|
10131 | 10431 | NULL, 1); |
---|
.. | .. |
---|
10134 | 10434 | /** |
---|
10135 | 10435 | * t4_i2c_rd - read I2C data from adapter |
---|
10136 | 10436 | * @adap: the adapter |
---|
| 10437 | + * @mbox: mailbox to use for the FW command |
---|
10137 | 10438 | * @port: Port number if per-port device; <0 if not |
---|
10138 | 10439 | * @devid: per-port device ID or absolute device ID |
---|
10139 | 10440 | * @offset: byte offset into device I2C space |
---|
.. | .. |
---|
10189 | 10490 | |
---|
10190 | 10491 | /** |
---|
10191 | 10492 | * t4_set_vlan_acl - Set a VLAN id for the specified VF |
---|
10192 | | - * @adapter: the adapter |
---|
| 10493 | + * @adap: the adapter |
---|
10193 | 10494 | * @mbox: mailbox to use for the FW command |
---|
10194 | 10495 | * @vf: one of the VFs instantiated by the specified PF |
---|
10195 | 10496 | * @vlan: The vlanid to be set |
---|
.. | .. |
---|
10210 | 10511 | FW_ACL_VLAN_CMD_VFN_V(vf)); |
---|
10211 | 10512 | vlan_cmd.en_to_len16 = cpu_to_be32(enable | FW_LEN16(vlan_cmd)); |
---|
10212 | 10513 | /* Drop all packets that donot match vlan id */ |
---|
10213 | | - vlan_cmd.dropnovlan_fm = FW_ACL_VLAN_CMD_FM_F; |
---|
| 10514 | + vlan_cmd.dropnovlan_fm = (enable |
---|
| 10515 | + ? (FW_ACL_VLAN_CMD_DROPNOVLAN_F | |
---|
| 10516 | + FW_ACL_VLAN_CMD_FM_F) : 0); |
---|
10214 | 10517 | if (enable != 0) { |
---|
10215 | 10518 | vlan_cmd.nvlan = 1; |
---|
10216 | 10519 | vlan_cmd.vlanid[0] = cpu_to_be16(vlan); |
---|
.. | .. |
---|
10218 | 10521 | |
---|
10219 | 10522 | return t4_wr_mbox(adap, adap->mbox, &vlan_cmd, sizeof(vlan_cmd), NULL); |
---|
10220 | 10523 | } |
---|
| 10524 | + |
---|
| 10525 | +/** |
---|
| 10526 | + * modify_device_id - Modifies the device ID of the Boot BIOS image |
---|
| 10527 | + * @device_id: the device ID to write. |
---|
| 10528 | + * @boot_data: the boot image to modify. |
---|
| 10529 | + * |
---|
| 10530 | + * Write the supplied device ID to the boot BIOS image. |
---|
| 10531 | + */ |
---|
| 10532 | +static void modify_device_id(int device_id, u8 *boot_data) |
---|
| 10533 | +{ |
---|
| 10534 | + struct cxgb4_pcir_data *pcir_header; |
---|
| 10535 | + struct legacy_pci_rom_hdr *header; |
---|
| 10536 | + u8 *cur_header = boot_data; |
---|
| 10537 | + u16 pcir_offset; |
---|
| 10538 | + |
---|
| 10539 | + /* Loop through all chained images and change the device ID's */ |
---|
| 10540 | + do { |
---|
| 10541 | + header = (struct legacy_pci_rom_hdr *)cur_header; |
---|
| 10542 | + pcir_offset = le16_to_cpu(header->pcir_offset); |
---|
| 10543 | + pcir_header = (struct cxgb4_pcir_data *)(cur_header + |
---|
| 10544 | + pcir_offset); |
---|
| 10545 | + |
---|
| 10546 | + /** |
---|
| 10547 | + * Only modify the Device ID if code type is Legacy or HP. |
---|
| 10548 | + * 0x00: Okay to modify |
---|
| 10549 | + * 0x01: FCODE. Do not modify |
---|
| 10550 | + * 0x03: Okay to modify |
---|
| 10551 | + * 0x04-0xFF: Do not modify |
---|
| 10552 | + */ |
---|
| 10553 | + if (pcir_header->code_type == CXGB4_HDR_CODE1) { |
---|
| 10554 | + u8 csum = 0; |
---|
| 10555 | + int i; |
---|
| 10556 | + |
---|
| 10557 | + /** |
---|
| 10558 | + * Modify Device ID to match current adatper |
---|
| 10559 | + */ |
---|
| 10560 | + pcir_header->device_id = cpu_to_le16(device_id); |
---|
| 10561 | + |
---|
| 10562 | + /** |
---|
| 10563 | + * Set checksum temporarily to 0. |
---|
| 10564 | + * We will recalculate it later. |
---|
| 10565 | + */ |
---|
| 10566 | + header->cksum = 0x0; |
---|
| 10567 | + |
---|
| 10568 | + /** |
---|
| 10569 | + * Calculate and update checksum |
---|
| 10570 | + */ |
---|
| 10571 | + for (i = 0; i < (header->size512 * 512); i++) |
---|
| 10572 | + csum += cur_header[i]; |
---|
| 10573 | + |
---|
| 10574 | + /** |
---|
| 10575 | + * Invert summed value to create the checksum |
---|
| 10576 | + * Writing new checksum value directly to the boot data |
---|
| 10577 | + */ |
---|
| 10578 | + cur_header[7] = -csum; |
---|
| 10579 | + |
---|
| 10580 | + } else if (pcir_header->code_type == CXGB4_HDR_CODE2) { |
---|
| 10581 | + /** |
---|
| 10582 | + * Modify Device ID to match current adatper |
---|
| 10583 | + */ |
---|
| 10584 | + pcir_header->device_id = cpu_to_le16(device_id); |
---|
| 10585 | + } |
---|
| 10586 | + |
---|
| 10587 | + /** |
---|
| 10588 | + * Move header pointer up to the next image in the ROM. |
---|
| 10589 | + */ |
---|
| 10590 | + cur_header += header->size512 * 512; |
---|
| 10591 | + } while (!(pcir_header->indicator & CXGB4_HDR_INDI)); |
---|
| 10592 | +} |
---|
| 10593 | + |
---|
| 10594 | +/** |
---|
| 10595 | + * t4_load_boot - download boot flash |
---|
| 10596 | + * @adap: the adapter |
---|
| 10597 | + * @boot_data: the boot image to write |
---|
| 10598 | + * @boot_addr: offset in flash to write boot_data |
---|
| 10599 | + * @size: image size |
---|
| 10600 | + * |
---|
| 10601 | + * Write the supplied boot image to the card's serial flash. |
---|
| 10602 | + * The boot image has the following sections: a 28-byte header and the |
---|
| 10603 | + * boot image. |
---|
| 10604 | + */ |
---|
| 10605 | +int t4_load_boot(struct adapter *adap, u8 *boot_data, |
---|
| 10606 | + unsigned int boot_addr, unsigned int size) |
---|
| 10607 | +{ |
---|
| 10608 | + unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec; |
---|
| 10609 | + unsigned int boot_sector = (boot_addr * 1024); |
---|
| 10610 | + struct cxgb4_pci_exp_rom_header *header; |
---|
| 10611 | + struct cxgb4_pcir_data *pcir_header; |
---|
| 10612 | + int pcir_offset; |
---|
| 10613 | + unsigned int i; |
---|
| 10614 | + u16 device_id; |
---|
| 10615 | + int ret, addr; |
---|
| 10616 | + |
---|
| 10617 | + /** |
---|
| 10618 | + * Make sure the boot image does not encroach on the firmware region |
---|
| 10619 | + */ |
---|
| 10620 | + if ((boot_sector + size) >> 16 > FLASH_FW_START_SEC) { |
---|
| 10621 | + dev_err(adap->pdev_dev, "boot image encroaching on firmware region\n"); |
---|
| 10622 | + return -EFBIG; |
---|
| 10623 | + } |
---|
| 10624 | + |
---|
| 10625 | + /* Get boot header */ |
---|
| 10626 | + header = (struct cxgb4_pci_exp_rom_header *)boot_data; |
---|
| 10627 | + pcir_offset = le16_to_cpu(header->pcir_offset); |
---|
| 10628 | + /* PCIR Data Structure */ |
---|
| 10629 | + pcir_header = (struct cxgb4_pcir_data *)&boot_data[pcir_offset]; |
---|
| 10630 | + |
---|
| 10631 | + /** |
---|
| 10632 | + * Perform some primitive sanity testing to avoid accidentally |
---|
| 10633 | + * writing garbage over the boot sectors. We ought to check for |
---|
| 10634 | + * more but it's not worth it for now ... |
---|
| 10635 | + */ |
---|
| 10636 | + if (size < BOOT_MIN_SIZE || size > BOOT_MAX_SIZE) { |
---|
| 10637 | + dev_err(adap->pdev_dev, "boot image too small/large\n"); |
---|
| 10638 | + return -EFBIG; |
---|
| 10639 | + } |
---|
| 10640 | + |
---|
| 10641 | + if (le16_to_cpu(header->signature) != BOOT_SIGNATURE) { |
---|
| 10642 | + dev_err(adap->pdev_dev, "Boot image missing signature\n"); |
---|
| 10643 | + return -EINVAL; |
---|
| 10644 | + } |
---|
| 10645 | + |
---|
| 10646 | + /* Check PCI header signature */ |
---|
| 10647 | + if (le32_to_cpu(pcir_header->signature) != PCIR_SIGNATURE) { |
---|
| 10648 | + dev_err(adap->pdev_dev, "PCI header missing signature\n"); |
---|
| 10649 | + return -EINVAL; |
---|
| 10650 | + } |
---|
| 10651 | + |
---|
| 10652 | + /* Check Vendor ID matches Chelsio ID*/ |
---|
| 10653 | + if (le16_to_cpu(pcir_header->vendor_id) != PCI_VENDOR_ID_CHELSIO) { |
---|
| 10654 | + dev_err(adap->pdev_dev, "Vendor ID missing signature\n"); |
---|
| 10655 | + return -EINVAL; |
---|
| 10656 | + } |
---|
| 10657 | + |
---|
| 10658 | + /** |
---|
| 10659 | + * The boot sector is comprised of the Expansion-ROM boot, iSCSI boot, |
---|
| 10660 | + * and Boot configuration data sections. These 3 boot sections span |
---|
| 10661 | + * sectors 0 to 7 in flash and live right before the FW image location. |
---|
| 10662 | + */ |
---|
| 10663 | + i = DIV_ROUND_UP(size ? size : FLASH_FW_START, sf_sec_size); |
---|
| 10664 | + ret = t4_flash_erase_sectors(adap, boot_sector >> 16, |
---|
| 10665 | + (boot_sector >> 16) + i - 1); |
---|
| 10666 | + |
---|
| 10667 | + /** |
---|
| 10668 | + * If size == 0 then we're simply erasing the FLASH sectors associated |
---|
| 10669 | + * with the on-adapter option ROM file |
---|
| 10670 | + */ |
---|
| 10671 | + if (ret || size == 0) |
---|
| 10672 | + goto out; |
---|
| 10673 | + /* Retrieve adapter's device ID */ |
---|
| 10674 | + pci_read_config_word(adap->pdev, PCI_DEVICE_ID, &device_id); |
---|
| 10675 | + /* Want to deal with PF 0 so I strip off PF 4 indicator */ |
---|
| 10676 | + device_id = device_id & 0xf0ff; |
---|
| 10677 | + |
---|
| 10678 | + /* Check PCIE Device ID */ |
---|
| 10679 | + if (le16_to_cpu(pcir_header->device_id) != device_id) { |
---|
| 10680 | + /** |
---|
| 10681 | + * Change the device ID in the Boot BIOS image to match |
---|
| 10682 | + * the Device ID of the current adapter. |
---|
| 10683 | + */ |
---|
| 10684 | + modify_device_id(device_id, boot_data); |
---|
| 10685 | + } |
---|
| 10686 | + |
---|
| 10687 | + /** |
---|
| 10688 | + * Skip over the first SF_PAGE_SIZE worth of data and write it after |
---|
| 10689 | + * we finish copying the rest of the boot image. This will ensure |
---|
| 10690 | + * that the BIOS boot header will only be written if the boot image |
---|
| 10691 | + * was written in full. |
---|
| 10692 | + */ |
---|
| 10693 | + addr = boot_sector; |
---|
| 10694 | + for (size -= SF_PAGE_SIZE; size; size -= SF_PAGE_SIZE) { |
---|
| 10695 | + addr += SF_PAGE_SIZE; |
---|
| 10696 | + boot_data += SF_PAGE_SIZE; |
---|
| 10697 | + ret = t4_write_flash(adap, addr, SF_PAGE_SIZE, boot_data, |
---|
| 10698 | + false); |
---|
| 10699 | + if (ret) |
---|
| 10700 | + goto out; |
---|
| 10701 | + } |
---|
| 10702 | + |
---|
| 10703 | + ret = t4_write_flash(adap, boot_sector, SF_PAGE_SIZE, |
---|
| 10704 | + (const u8 *)header, false); |
---|
| 10705 | + |
---|
| 10706 | +out: |
---|
| 10707 | + if (ret) |
---|
| 10708 | + dev_err(adap->pdev_dev, "boot image load failed, error %d\n", |
---|
| 10709 | + ret); |
---|
| 10710 | + return ret; |
---|
| 10711 | +} |
---|
| 10712 | + |
---|
| 10713 | +/** |
---|
| 10714 | + * t4_flash_bootcfg_addr - return the address of the flash |
---|
| 10715 | + * optionrom configuration |
---|
| 10716 | + * @adapter: the adapter |
---|
| 10717 | + * |
---|
| 10718 | + * Return the address within the flash where the OptionROM Configuration |
---|
| 10719 | + * is stored, or an error if the device FLASH is too small to contain |
---|
| 10720 | + * a OptionROM Configuration. |
---|
| 10721 | + */ |
---|
| 10722 | +static int t4_flash_bootcfg_addr(struct adapter *adapter) |
---|
| 10723 | +{ |
---|
| 10724 | + /** |
---|
| 10725 | + * If the device FLASH isn't large enough to hold a Firmware |
---|
| 10726 | + * Configuration File, return an error. |
---|
| 10727 | + */ |
---|
| 10728 | + if (adapter->params.sf_size < |
---|
| 10729 | + FLASH_BOOTCFG_START + FLASH_BOOTCFG_MAX_SIZE) |
---|
| 10730 | + return -ENOSPC; |
---|
| 10731 | + |
---|
| 10732 | + return FLASH_BOOTCFG_START; |
---|
| 10733 | +} |
---|
| 10734 | + |
---|
| 10735 | +int t4_load_bootcfg(struct adapter *adap, const u8 *cfg_data, unsigned int size) |
---|
| 10736 | +{ |
---|
| 10737 | + unsigned int sf_sec_size = adap->params.sf_size / adap->params.sf_nsec; |
---|
| 10738 | + struct cxgb4_bootcfg_data *header; |
---|
| 10739 | + unsigned int flash_cfg_start_sec; |
---|
| 10740 | + unsigned int addr, npad; |
---|
| 10741 | + int ret, i, n, cfg_addr; |
---|
| 10742 | + |
---|
| 10743 | + cfg_addr = t4_flash_bootcfg_addr(adap); |
---|
| 10744 | + if (cfg_addr < 0) |
---|
| 10745 | + return cfg_addr; |
---|
| 10746 | + |
---|
| 10747 | + addr = cfg_addr; |
---|
| 10748 | + flash_cfg_start_sec = addr / SF_SEC_SIZE; |
---|
| 10749 | + |
---|
| 10750 | + if (size > FLASH_BOOTCFG_MAX_SIZE) { |
---|
| 10751 | + dev_err(adap->pdev_dev, "bootcfg file too large, max is %u bytes\n", |
---|
| 10752 | + FLASH_BOOTCFG_MAX_SIZE); |
---|
| 10753 | + return -EFBIG; |
---|
| 10754 | + } |
---|
| 10755 | + |
---|
| 10756 | + header = (struct cxgb4_bootcfg_data *)cfg_data; |
---|
| 10757 | + if (le16_to_cpu(header->signature) != BOOT_CFG_SIG) { |
---|
| 10758 | + dev_err(adap->pdev_dev, "Wrong bootcfg signature\n"); |
---|
| 10759 | + ret = -EINVAL; |
---|
| 10760 | + goto out; |
---|
| 10761 | + } |
---|
| 10762 | + |
---|
| 10763 | + i = DIV_ROUND_UP(FLASH_BOOTCFG_MAX_SIZE, |
---|
| 10764 | + sf_sec_size); |
---|
| 10765 | + ret = t4_flash_erase_sectors(adap, flash_cfg_start_sec, |
---|
| 10766 | + flash_cfg_start_sec + i - 1); |
---|
| 10767 | + |
---|
| 10768 | + /** |
---|
| 10769 | + * If size == 0 then we're simply erasing the FLASH sectors associated |
---|
| 10770 | + * with the on-adapter OptionROM Configuration File. |
---|
| 10771 | + */ |
---|
| 10772 | + if (ret || size == 0) |
---|
| 10773 | + goto out; |
---|
| 10774 | + |
---|
| 10775 | + /* this will write to the flash up to SF_PAGE_SIZE at a time */ |
---|
| 10776 | + for (i = 0; i < size; i += SF_PAGE_SIZE) { |
---|
| 10777 | + n = min_t(u32, size - i, SF_PAGE_SIZE); |
---|
| 10778 | + |
---|
| 10779 | + ret = t4_write_flash(adap, addr, n, cfg_data, false); |
---|
| 10780 | + if (ret) |
---|
| 10781 | + goto out; |
---|
| 10782 | + |
---|
| 10783 | + addr += SF_PAGE_SIZE; |
---|
| 10784 | + cfg_data += SF_PAGE_SIZE; |
---|
| 10785 | + } |
---|
| 10786 | + |
---|
| 10787 | + npad = ((size + 4 - 1) & ~3) - size; |
---|
| 10788 | + for (i = 0; i < npad; i++) { |
---|
| 10789 | + u8 data = 0; |
---|
| 10790 | + |
---|
| 10791 | + ret = t4_write_flash(adap, cfg_addr + size + i, 1, &data, |
---|
| 10792 | + false); |
---|
| 10793 | + if (ret) |
---|
| 10794 | + goto out; |
---|
| 10795 | + } |
---|
| 10796 | + |
---|
| 10797 | +out: |
---|
| 10798 | + if (ret) |
---|
| 10799 | + dev_err(adap->pdev_dev, "boot config data %s failed %d\n", |
---|
| 10800 | + (size == 0 ? "clear" : "download"), ret); |
---|
| 10801 | + return ret; |
---|
| 10802 | +} |
---|