Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Bogendoerfer <tbogendoerfer@suse.de>2018-03-16 10:44:35 +0100
committerThomas Bogendoerfer <tbogendoerfer@suse.de>2018-03-16 10:44:35 +0100
commit2a6691d40319b93e01d7233122867617448a5ed5 (patch)
tree4dbe744d8f8995bc0571ffa04deafe71d7ee8462
parentbe1466381fea0e85b42c437bb6e7048f9201d3d1 (diff)
scsi: csiostor: add support for 32 bit port capabilities
(bsc#1084463).
-rw-r--r--patches.drivers/scsi-csiostor-add-support-for-32-bit-port-capabiliti.patch634
-rw-r--r--series.conf3
2 files changed, 637 insertions, 0 deletions
diff --git a/patches.drivers/scsi-csiostor-add-support-for-32-bit-port-capabiliti.patch b/patches.drivers/scsi-csiostor-add-support-for-32-bit-port-capabiliti.patch
new file mode 100644
index 0000000000..273981befd
--- /dev/null
+++ b/patches.drivers/scsi-csiostor-add-support-for-32-bit-port-capabiliti.patch
@@ -0,0 +1,634 @@
+From: Varun Prakash <varun@chelsio.com>
+Date: Sun, 11 Mar 2018 18:02:13 +0530
+Subject: scsi: csiostor: add support for 32 bit port capabilities
+Patch-mainline: Queued in subsystem maintainer repository
+Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/mkp/scsi.git
+Git-commit: e1735d9a98ab5593484bbba1933e362a261e0de0
+References: bsc#1084463
+
+32 bit port capabilities are required to support new speeds which can
+not be supported using 16 bit port capabilities.
+
+Signed-off-by: Varun Prakash <varun@chelsio.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
+---
+ drivers/scsi/csiostor/csio_attr.c | 16 +-
+ drivers/scsi/csiostor/csio_hw.c | 275 ++++++++++++++++++++++++++++++++++++-
+ drivers/scsi/csiostor/csio_hw.h | 59 +++++++
+ drivers/scsi/csiostor/csio_lnode.c | 8 +
+ drivers/scsi/csiostor/csio_mb.c | 70 +++++----
+ drivers/scsi/csiostor/csio_mb.h | 9 -
+ 6 files changed, 395 insertions(+), 42 deletions(-)
+
+--- a/drivers/scsi/csiostor/csio_attr.c
++++ b/drivers/scsi/csiostor/csio_attr.c
+@@ -274,12 +274,24 @@ csio_get_host_speed(struct Scsi_Host *sh
+
+ spin_lock_irq(&hw->lock);
+ switch (hw->pport[ln->portid].link_speed) {
+- case FW_PORT_CAP_SPEED_1G:
++ case FW_PORT_CAP32_SPEED_1G:
+ fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
+ break;
+- case FW_PORT_CAP_SPEED_10G:
++ case FW_PORT_CAP32_SPEED_10G:
+ fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
+ break;
++ case FW_PORT_CAP32_SPEED_25G:
++ fc_host_speed(shost) = FC_PORTSPEED_25GBIT;
++ break;
++ case FW_PORT_CAP32_SPEED_40G:
++ fc_host_speed(shost) = FC_PORTSPEED_40GBIT;
++ break;
++ case FW_PORT_CAP32_SPEED_50G:
++ fc_host_speed(shost) = FC_PORTSPEED_50GBIT;
++ break;
++ case FW_PORT_CAP32_SPEED_100G:
++ fc_host_speed(shost) = FC_PORTSPEED_100GBIT;
++ break;
+ default:
+ fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
+ break;
+--- a/drivers/scsi/csiostor/csio_hw.c
++++ b/drivers/scsi/csiostor/csio_hw.c
+@@ -1409,6 +1409,235 @@ out:
+ return rv;
+ }
+
++static inline enum cc_fec fwcap_to_cc_fec(fw_port_cap32_t fw_fec)
++{
++ enum cc_fec cc_fec = 0;
++
++ if (fw_fec & FW_PORT_CAP32_FEC_RS)
++ cc_fec |= FEC_RS;
++ if (fw_fec & FW_PORT_CAP32_FEC_BASER_RS)
++ cc_fec |= FEC_BASER_RS;
++
++ return cc_fec;
++}
++
++static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
++{
++ fw_port_cap32_t fw_pause = 0;
++
++ if (cc_pause & PAUSE_RX)
++ fw_pause |= FW_PORT_CAP32_FC_RX;
++ if (cc_pause & PAUSE_TX)
++ fw_pause |= FW_PORT_CAP32_FC_TX;
++
++ return fw_pause;
++}
++
++static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
++{
++ fw_port_cap32_t fw_fec = 0;
++
++ if (cc_fec & FEC_RS)
++ fw_fec |= FW_PORT_CAP32_FEC_RS;
++ if (cc_fec & FEC_BASER_RS)
++ fw_fec |= FW_PORT_CAP32_FEC_BASER_RS;
++
++ return fw_fec;
++}
++
++/**
++ * fwcap_to_fwspeed - return highest speed in Port Capabilities
++ * @acaps: advertised Port Capabilities
++ *
++ * Get the highest speed for the port from the advertised Port
++ * Capabilities.
++ */
++fw_port_cap32_t fwcap_to_fwspeed(fw_port_cap32_t acaps)
++{
++ #define TEST_SPEED_RETURN(__caps_speed) \
++ do { \
++ if (acaps & FW_PORT_CAP32_SPEED_##__caps_speed) \
++ return FW_PORT_CAP32_SPEED_##__caps_speed; \
++ } while (0)
++
++ TEST_SPEED_RETURN(400G);
++ TEST_SPEED_RETURN(200G);
++ TEST_SPEED_RETURN(100G);
++ TEST_SPEED_RETURN(50G);
++ TEST_SPEED_RETURN(40G);
++ TEST_SPEED_RETURN(25G);
++ TEST_SPEED_RETURN(10G);
++ TEST_SPEED_RETURN(1G);
++ TEST_SPEED_RETURN(100M);
++
++ #undef TEST_SPEED_RETURN
++
++ return 0;
++}
++
++/**
++ * fwcaps16_to_caps32 - convert 16-bit Port Capabilities to 32-bits
++ * @caps16: a 16-bit Port Capabilities value
++ *
++ * Returns the equivalent 32-bit Port Capabilities value.
++ */
++fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16)
++{
++ fw_port_cap32_t caps32 = 0;
++
++ #define CAP16_TO_CAP32(__cap) \
++ do { \
++ if (caps16 & FW_PORT_CAP_##__cap) \
++ caps32 |= FW_PORT_CAP32_##__cap; \
++ } while (0)
++
++ CAP16_TO_CAP32(SPEED_100M);
++ CAP16_TO_CAP32(SPEED_1G);
++ CAP16_TO_CAP32(SPEED_25G);
++ CAP16_TO_CAP32(SPEED_10G);
++ CAP16_TO_CAP32(SPEED_40G);
++ CAP16_TO_CAP32(SPEED_100G);
++ CAP16_TO_CAP32(FC_RX);
++ CAP16_TO_CAP32(FC_TX);
++ CAP16_TO_CAP32(ANEG);
++ CAP16_TO_CAP32(MDIX);
++ CAP16_TO_CAP32(MDIAUTO);
++ CAP16_TO_CAP32(FEC_RS);
++ CAP16_TO_CAP32(FEC_BASER_RS);
++ CAP16_TO_CAP32(802_3_PAUSE);
++ CAP16_TO_CAP32(802_3_ASM_DIR);
++
++ #undef CAP16_TO_CAP32
++
++ return caps32;
++}
++
++/**
++ * lstatus_to_fwcap - translate old lstatus to 32-bit Port Capabilities
++ * @lstatus: old FW_PORT_ACTION_GET_PORT_INFO lstatus value
++ *
++ * Translates old FW_PORT_ACTION_GET_PORT_INFO lstatus field into new
++ * 32-bit Port Capabilities value.
++ */
++fw_port_cap32_t lstatus_to_fwcap(u32 lstatus)
++{
++ fw_port_cap32_t linkattr = 0;
++
++ /* The format of the Link Status in the old
++ * 16-bit Port Information message isn't the same as the
++ * 16-bit Port Capabilities bitfield used everywhere else.
++ */
++ if (lstatus & FW_PORT_CMD_RXPAUSE_F)
++ linkattr |= FW_PORT_CAP32_FC_RX;
++ if (lstatus & FW_PORT_CMD_TXPAUSE_F)
++ linkattr |= FW_PORT_CAP32_FC_TX;
++ if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M))
++ linkattr |= FW_PORT_CAP32_SPEED_100M;
++ if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G))
++ linkattr |= FW_PORT_CAP32_SPEED_1G;
++ if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G))
++ linkattr |= FW_PORT_CAP32_SPEED_10G;
++ if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_25G))
++ linkattr |= FW_PORT_CAP32_SPEED_25G;
++ if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G))
++ linkattr |= FW_PORT_CAP32_SPEED_40G;
++ if (lstatus & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100G))
++ linkattr |= FW_PORT_CAP32_SPEED_100G;
++
++ return linkattr;
++}
++
++/**
++ * csio_init_link_config - initialize a link's SW state
++ * @lc: pointer to structure holding the link state
++ * @pcaps: link Port Capabilities
++ * @acaps: link current Advertised Port Capabilities
++ *
++ * Initializes the SW state maintained for each link, including the link's
++ * capabilities and default speed/flow-control/autonegotiation settings.
++ */
++static void csio_init_link_config(struct link_config *lc, fw_port_cap32_t pcaps,
++ fw_port_cap32_t acaps)
++{
++ lc->pcaps = pcaps;
++ lc->def_acaps = acaps;
++ lc->lpacaps = 0;
++ lc->speed_caps = 0;
++ lc->speed = 0;
++ lc->requested_fc = PAUSE_RX | PAUSE_TX;
++ lc->fc = lc->requested_fc;
++
++ /*
++ * For Forward Error Control, we default to whatever the Firmware
++ * tells us the Link is currently advertising.
++ */
++ lc->requested_fec = FEC_AUTO;
++ lc->fec = fwcap_to_cc_fec(lc->def_acaps);
++
++ /* If the Port is capable of Auto-Negtotiation, initialize it as
++ * "enabled" and copy over all of the Physical Port Capabilities
++ * to the Advertised Port Capabilities. Otherwise mark it as
++ * Auto-Negotiate disabled and select the highest supported speed
++ * for the link. Note parallel structure in t4_link_l1cfg_core()
++ * and t4_handle_get_port_info().
++ */
++ if (lc->pcaps & FW_PORT_CAP32_ANEG) {
++ lc->acaps = lc->pcaps & ADVERT_MASK;
++ lc->autoneg = AUTONEG_ENABLE;
++ lc->requested_fc |= PAUSE_AUTONEG;
++ } else {
++ lc->acaps = 0;
++ lc->autoneg = AUTONEG_DISABLE;
++ }
++}
++
++static void csio_link_l1cfg(struct link_config *lc, uint16_t fw_caps,
++ uint32_t *rcaps)
++{
++ unsigned int fw_mdi = FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO);
++ fw_port_cap32_t fw_fc, cc_fec, fw_fec, lrcap;
++
++ lc->link_ok = 0;
++
++ /*
++ * Convert driver coding of Pause Frame Flow Control settings into the
++ * Firmware's API.
++ */
++ fw_fc = cc_to_fwcap_pause(lc->requested_fc);
++
++ /*
++ * Convert Common Code Forward Error Control settings into the
++ * Firmware's API. If the current Requested FEC has "Automatic"
++ * (IEEE 802.3) specified, then we use whatever the Firmware
++ * sent us as part of it's IEEE 802.3-based interpratation of
++ * the Transceiver Module EPROM FEC parameters. Otherwise we
++ * use whatever is in the current Requested FEC settings.
++ */
++ if (lc->requested_fec & FEC_AUTO)
++ cc_fec = fwcap_to_cc_fec(lc->def_acaps);
++ else
++ cc_fec = lc->requested_fec;
++ fw_fec = cc_to_fwcap_fec(cc_fec);
++
++ /* Figure out what our Requested Port Capabilities are going to be.
++ * Note parallel structure in t4_handle_get_port_info() and
++ * init_link_config().
++ */
++ if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
++ lrcap = (lc->pcaps & ADVERT_MASK) | fw_fc | fw_fec;
++ lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
++ lc->fec = cc_fec;
++ } else if (lc->autoneg == AUTONEG_DISABLE) {
++ lrcap = lc->speed_caps | fw_fc | fw_fec | fw_mdi;
++ lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
++ lc->fec = cc_fec;
++ } else {
++ lrcap = lc->acaps | fw_fc | fw_fec | fw_mdi;
++ }
++
++ *rcaps = lrcap;
++}
++
+ /*
+ * csio_enable_ports - Bring up all available ports.
+ * @hw: HW module.
+@@ -1418,8 +1647,10 @@ static int
+ csio_enable_ports(struct csio_hw *hw)
+ {
+ struct csio_mb *mbp;
++ u16 fw_caps = FW_CAPS_UNKNOWN;
+ enum fw_retval retval;
+ uint8_t portid;
++ fw_port_cap32_t pcaps, acaps, rcaps;
+ int i;
+
+ mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
+@@ -1431,9 +1662,39 @@ csio_enable_ports(struct csio_hw *hw)
+ for (i = 0; i < hw->num_pports; i++) {
+ portid = hw->pport[i].portid;
+
++ if (fw_caps == FW_CAPS_UNKNOWN) {
++ u32 param, val;
++
++ param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) |
++ FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_PORT_CAPS32));
++ val = 1;
++
++ csio_mb_params(hw, mbp, CSIO_MB_DEFAULT_TMO,
++ hw->pfn, 0, 1, &param, &val, false,
++ NULL);
++
++ if (csio_mb_issue(hw, mbp)) {
++ csio_err(hw, "failed to issue FW_PARAMS_CMD(r) port:%d\n",
++ portid);
++ mempool_free(mbp, hw->mb_mempool);
++ return -EINVAL;
++ }
++
++ csio_mb_process_read_params_rsp(hw, mbp, &retval, 1,
++ &val);
++ if (retval != FW_SUCCESS) {
++ csio_err(hw, "FW_PARAMS_CMD(r) port:%d failed: 0x%x\n",
++ portid, retval);
++ mempool_free(mbp, hw->mb_mempool);
++ return -EINVAL;
++ }
++
++ fw_caps = val;
++ }
++
+ /* Read PORT information */
+ csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid,
+- false, 0, 0, NULL);
++ false, 0, fw_caps, NULL);
+
+ if (csio_mb_issue(hw, mbp)) {
+ csio_err(hw, "failed to issue FW_PORT_CMD(r) port:%d\n",
+@@ -1442,8 +1703,8 @@ csio_enable_ports(struct csio_hw *hw)
+ return -EINVAL;
+ }
+
+- csio_mb_process_read_port_rsp(hw, mbp, &retval,
+- &hw->pport[i].pcap);
++ csio_mb_process_read_port_rsp(hw, mbp, &retval, fw_caps,
++ &pcaps, &acaps);
+ if (retval != FW_SUCCESS) {
+ csio_err(hw, "FW_PORT_CMD(r) port:%d failed: 0x%x\n",
+ portid, retval);
+@@ -1451,9 +1712,13 @@ csio_enable_ports(struct csio_hw *hw)
+ return -EINVAL;
+ }
+
++ csio_init_link_config(&hw->pport[i].link_cfg, pcaps, acaps);
++
++ csio_link_l1cfg(&hw->pport[i].link_cfg, fw_caps, &rcaps);
++
+ /* Write back PORT information */
+- csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid, true,
+- (PAUSE_RX | PAUSE_TX), hw->pport[i].pcap, NULL);
++ csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid,
++ true, rcaps, fw_caps, NULL);
+
+ if (csio_mb_issue(hw, mbp)) {
+ csio_err(hw, "failed to issue FW_PORT_CMD(w) port:%d\n",
+--- a/drivers/scsi/csiostor/csio_hw.h
++++ b/drivers/scsi/csiostor/csio_hw.h
+@@ -268,8 +268,62 @@ struct csio_vpd {
+ uint8_t id[ID_LEN + 1];
+ };
+
++/* Firmware Port Capabilities types. */
++
++typedef u16 fw_port_cap16_t; /* 16-bit Port Capabilities integral value */
++typedef u32 fw_port_cap32_t; /* 32-bit Port Capabilities integral value */
++
++enum fw_caps {
++ FW_CAPS_UNKNOWN = 0, /* 0'ed out initial state */
++ FW_CAPS16 = 1, /* old Firmware: 16-bit Port Capabilities */
++ FW_CAPS32 = 2, /* new Firmware: 32-bit Port Capabilities */
++};
++
++enum cc_pause {
++ PAUSE_RX = 1 << 0,
++ PAUSE_TX = 1 << 1,
++ PAUSE_AUTONEG = 1 << 2
++};
++
++enum cc_fec {
++ FEC_AUTO = 1 << 0, /* IEEE 802.3 "automatic" */
++ FEC_RS = 1 << 1, /* Reed-Solomon */
++ FEC_BASER_RS = 1 << 2 /* BaseR/Reed-Solomon */
++};
++
++struct link_config {
++ fw_port_cap32_t pcaps; /* link capabilities */
++ fw_port_cap32_t def_acaps; /* default advertised capabilities */
++ fw_port_cap32_t acaps; /* advertised capabilities */
++ fw_port_cap32_t lpacaps; /* peer advertised capabilities */
++
++ fw_port_cap32_t speed_caps; /* speed(s) user has requested */
++ unsigned int speed; /* actual link speed (Mb/s) */
++
++ enum cc_pause requested_fc; /* flow control user has requested */
++ enum cc_pause fc; /* actual link flow control */
++
++ enum cc_fec requested_fec; /* Forward Error Correction: */
++ enum cc_fec fec; /* requested and actual in use */
++
++ unsigned char autoneg; /* autonegotiating? */
++
++ unsigned char link_ok; /* link up? */
++ unsigned char link_down_rc; /* link down reason */
++};
++
++#define FW_LEN16(fw_struct) FW_CMD_LEN16_V(sizeof(fw_struct) / 16)
++
++#define ADVERT_MASK (FW_PORT_CAP32_SPEED_V(FW_PORT_CAP32_SPEED_M) | \
++ FW_PORT_CAP32_ANEG)
++
++/* Enable or disable autonegotiation. */
++#define AUTONEG_DISABLE 0x00
++#define AUTONEG_ENABLE 0x01
++
+ struct csio_pport {
+ uint16_t pcap;
++ uint16_t acap;
+ uint8_t portid;
+ uint8_t link_status;
+ uint16_t link_speed;
+@@ -278,6 +332,7 @@ struct csio_pport {
+ uint8_t rsvd1;
+ uint8_t rsvd2;
+ uint8_t rsvd3;
++ struct link_config link_cfg;
+ };
+
+ /* fcoe resource information */
+@@ -582,6 +637,10 @@ int csio_hw_slow_intr_handler(struct csi
+ int csio_handle_intr_status(struct csio_hw *, unsigned int,
+ const struct intr_info *);
+
++fw_port_cap32_t fwcap_to_fwspeed(fw_port_cap32_t acaps);
++fw_port_cap32_t fwcaps16_to_caps32(fw_port_cap16_t caps16);
++fw_port_cap32_t lstatus_to_fwcap(u32 lstatus);
++
+ int csio_hw_start(struct csio_hw *);
+ int csio_hw_stop(struct csio_hw *);
+ int csio_hw_reset(struct csio_hw *);
+--- a/drivers/scsi/csiostor/csio_lnode.c
++++ b/drivers/scsi/csiostor/csio_lnode.c
+@@ -352,6 +352,14 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *h
+ val = htonl(FC_PORTSPEED_1GBIT);
+ else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_10G)
+ val = htonl(FC_PORTSPEED_10GBIT);
++ else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_25G)
++ val = htonl(FC_PORTSPEED_25GBIT);
++ else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_40G)
++ val = htonl(FC_PORTSPEED_40GBIT);
++ else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_50G)
++ val = htonl(FC_PORTSPEED_50GBIT);
++ else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP32_SPEED_100G)
++ val = htonl(FC_PORTSPEED_100GBIT);
+ else
+ val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN);
+ csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
+--- a/drivers/scsi/csiostor/csio_mb.c
++++ b/drivers/scsi/csiostor/csio_mb.c
+@@ -326,10 +326,6 @@ csio_mb_caps_config(struct csio_hw *hw,
+ cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_TARGET);
+ }
+
+-#define CSIO_ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\
+- FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G |\
+- FW_PORT_CAP_ANEG)
+-
+ /*
+ * csio_mb_port- FW PORT command helper
+ * @hw: The HW structure
+@@ -344,11 +340,10 @@ csio_mb_caps_config(struct csio_hw *hw,
+ */
+ void
+ csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
+- uint8_t portid, bool wr, uint32_t fc, uint16_t caps,
++ u8 portid, bool wr, uint32_t fc, uint16_t fw_caps,
+ void (*cbfn) (struct csio_hw *, struct csio_mb *))
+ {
+ struct fw_port_cmd *cmdp = (struct fw_port_cmd *)(mbp->mb);
+- unsigned int lfc = 0, mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO);
+
+ CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
+
+@@ -358,26 +353,24 @@ csio_mb_port(struct csio_hw *hw, struct
+ FW_PORT_CMD_PORTID_V(portid));
+ if (!wr) {
+ cmdp->action_to_len16 = htonl(
+- FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) |
++ FW_PORT_CMD_ACTION_V(fw_caps == FW_CAPS16
++ ? FW_PORT_ACTION_GET_PORT_INFO
++ : FW_PORT_ACTION_GET_PORT_INFO32) |
+ FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
+ return;
+ }
+
+ /* Set port */
+ cmdp->action_to_len16 = htonl(
+- FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_L1_CFG) |
++ FW_PORT_CMD_ACTION_V(fw_caps == FW_CAPS16
++ ? FW_PORT_ACTION_L1_CFG
++ : FW_PORT_ACTION_L1_CFG32) |
+ FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
+
+- if (fc & PAUSE_RX)
+- lfc |= FW_PORT_CAP_FC_RX;
+- if (fc & PAUSE_TX)
+- lfc |= FW_PORT_CAP_FC_TX;
+-
+- if (!(caps & FW_PORT_CAP_ANEG))
+- cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | lfc);
++ if (fw_caps == FW_CAPS16)
++ cmdp->u.l1cfg.rcap = cpu_to_be32(fc);
+ else
+- cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) |
+- lfc | mdi);
++ cmdp->u.l1cfg32.rcap32 = cpu_to_be32(fc);
+ }
+
+ /*
+@@ -390,14 +383,22 @@ csio_mb_port(struct csio_hw *hw, struct
+ */
+ void
+ csio_mb_process_read_port_rsp(struct csio_hw *hw, struct csio_mb *mbp,
+- enum fw_retval *retval, uint16_t *caps)
++ enum fw_retval *retval, uint16_t fw_caps,
++ u32 *pcaps, u32 *acaps)
+ {
+ struct fw_port_cmd *rsp = (struct fw_port_cmd *)(mbp->mb);
+
+ *retval = FW_CMD_RETVAL_G(ntohl(rsp->action_to_len16));
+
+- if (*retval == FW_SUCCESS)
+- *caps = ntohs(rsp->u.info.pcap);
++ if (*retval == FW_SUCCESS) {
++ if (fw_caps == FW_CAPS16) {
++ *pcaps = fwcaps16_to_caps32(ntohs(rsp->u.info.pcap));
++ *acaps = fwcaps16_to_caps32(ntohs(rsp->u.info.acap));
++ } else {
++ *pcaps = ntohs(rsp->u.info32.pcaps32);
++ *acaps = ntohs(rsp->u.info32.acaps32);
++ }
++ }
+ }
+
+ /*
+@@ -1409,6 +1410,7 @@ csio_mb_fwevt_handler(struct csio_hw *hw
+ uint32_t link_status;
+ uint16_t action;
+ uint8_t mod_type;
++ fw_port_cap32_t linkattr;
+
+ if (opcode == FW_PORT_CMD) {
+ pcmd = (struct fw_port_cmd *)cmd;
+@@ -1416,22 +1418,34 @@ csio_mb_fwevt_handler(struct csio_hw *hw
+ ntohl(pcmd->op_to_portid));
+ action = FW_PORT_CMD_ACTION_G(
+ ntohl(pcmd->action_to_len16));
+- if (action != FW_PORT_ACTION_GET_PORT_INFO) {
++ if (action != FW_PORT_ACTION_GET_PORT_INFO &&
++ action != FW_PORT_ACTION_GET_PORT_INFO32) {
+ csio_err(hw, "Unhandled FW_PORT_CMD action: %u\n",
+ action);
+ return -EINVAL;
+ }
+
+- link_status = ntohl(pcmd->u.info.lstatus_to_modtype);
+- mod_type = FW_PORT_CMD_MODTYPE_G(link_status);
++ if (action == FW_PORT_ACTION_GET_PORT_INFO) {
++ link_status = ntohl(pcmd->u.info.lstatus_to_modtype);
++ mod_type = FW_PORT_CMD_MODTYPE_G(link_status);
++ linkattr = lstatus_to_fwcap(link_status);
++
++ hw->pport[port_id].link_status =
++ FW_PORT_CMD_LSTATUS_G(link_status);
++ } else {
++ link_status =
++ ntohl(pcmd->u.info32.lstatus32_to_cbllen32);
++ mod_type = FW_PORT_CMD_MODTYPE32_G(link_status);
++ linkattr = ntohl(pcmd->u.info32.linkattr32);
++
++ hw->pport[port_id].link_status =
++ FW_PORT_CMD_LSTATUS32_G(link_status);
++ }
+
+- hw->pport[port_id].link_status =
+- FW_PORT_CMD_LSTATUS_G(link_status);
+- hw->pport[port_id].link_speed =
+- FW_PORT_CMD_LSPEED_G(link_status);
++ hw->pport[port_id].link_speed = fwcap_to_fwspeed(linkattr);
+
+ csio_info(hw, "Port:%x - LINK %s\n", port_id,
+- FW_PORT_CMD_LSTATUS_G(link_status) ? "UP" : "DOWN");
++ hw->pport[port_id].link_status ? "UP" : "DOWN");
+
+ if (mod_type != hw->pport[port_id].mod_type) {
+ hw->pport[port_id].mod_type = mod_type;
+--- a/drivers/scsi/csiostor/csio_mb.h
++++ b/drivers/scsi/csiostor/csio_mb.h
+@@ -88,12 +88,6 @@ enum csio_dev_state {
+ FW_PARAMS_PARAM_Y_V(0) | \
+ FW_PARAMS_PARAM_Z_V(0))
+
+-enum {
+- PAUSE_RX = 1 << 0,
+- PAUSE_TX = 1 << 1,
+- PAUSE_AUTONEG = 1 << 2
+-};
+-
+ #define CSIO_INIT_MBP(__mbp, __cp, __tmo, __priv, __fn, __clear) \
+ do { \
+ if (__clear) \
+@@ -188,7 +182,8 @@ void csio_mb_port(struct csio_hw *, stru
+ void (*) (struct csio_hw *, struct csio_mb *));
+
+ void csio_mb_process_read_port_rsp(struct csio_hw *, struct csio_mb *,
+- enum fw_retval *, uint16_t *);
++ enum fw_retval *, uint16_t,
++ uint32_t *, uint32_t *);
+
+ void csio_mb_initialize(struct csio_hw *, struct csio_mb *, uint32_t,
+ void (*)(struct csio_hw *, struct csio_mb *));
diff --git a/series.conf b/series.conf
index 218b140a89..fe2d1ffbb2 100644
--- a/series.conf
+++ b/series.conf
@@ -10870,6 +10870,9 @@
# jj/linux-apparmor apparmor-next
patches.apparmor/apparmor-fix-resource-audit-messages-when-auditing-peer.patch
+ # mkp/scsi 4.17/scsi-queue
+ patches.drivers/scsi-csiostor-add-support-for-32-bit-port-capabiliti.patch
+
# out-of-tree patches
patches.suse/arm64-add-PTE_ADDR_MASK.patch
patches.suse/btrfs-use-kvzalloc-to-allocate-btrfs_fs_info.patch