Commit e1735d9a authored by Varun Prakash's avatar Varun Prakash Committed by Martin K. Petersen

scsi: csiostor: add support for 32 bit port capabilities

32 bit port capabilities are required to support new speeds which can
not be supported using 16 bit port capabilities.
Signed-off-by: default avatarVarun Prakash <varun@chelsio.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 1929e82e
...@@ -274,12 +274,24 @@ csio_get_host_speed(struct Scsi_Host *shost) ...@@ -274,12 +274,24 @@ csio_get_host_speed(struct Scsi_Host *shost)
spin_lock_irq(&hw->lock); spin_lock_irq(&hw->lock);
switch (hw->pport[ln->portid].link_speed) { 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; fc_host_speed(shost) = FC_PORTSPEED_1GBIT;
break; break;
case FW_PORT_CAP_SPEED_10G: case FW_PORT_CAP32_SPEED_10G:
fc_host_speed(shost) = FC_PORTSPEED_10GBIT; fc_host_speed(shost) = FC_PORTSPEED_10GBIT;
break; 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: default:
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
break; break;
......
...@@ -1409,6 +1409,235 @@ csio_config_device_caps(struct csio_hw *hw) ...@@ -1409,6 +1409,235 @@ csio_config_device_caps(struct csio_hw *hw)
return rv; 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. * csio_enable_ports - Bring up all available ports.
* @hw: HW module. * @hw: HW module.
...@@ -1418,8 +1647,10 @@ static int ...@@ -1418,8 +1647,10 @@ static int
csio_enable_ports(struct csio_hw *hw) csio_enable_ports(struct csio_hw *hw)
{ {
struct csio_mb *mbp; struct csio_mb *mbp;
u16 fw_caps = FW_CAPS_UNKNOWN;
enum fw_retval retval; enum fw_retval retval;
uint8_t portid; uint8_t portid;
fw_port_cap32_t pcaps, acaps, rcaps;
int i; int i;
mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC); mbp = mempool_alloc(hw->mb_mempool, GFP_ATOMIC);
...@@ -1431,9 +1662,39 @@ csio_enable_ports(struct csio_hw *hw) ...@@ -1431,9 +1662,39 @@ csio_enable_ports(struct csio_hw *hw)
for (i = 0; i < hw->num_pports; i++) { for (i = 0; i < hw->num_pports; i++) {
portid = hw->pport[i].portid; 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 */ /* Read PORT information */
csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid, 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)) { if (csio_mb_issue(hw, mbp)) {
csio_err(hw, "failed to issue FW_PORT_CMD(r) port:%d\n", csio_err(hw, "failed to issue FW_PORT_CMD(r) port:%d\n",
...@@ -1442,8 +1703,8 @@ csio_enable_ports(struct csio_hw *hw) ...@@ -1442,8 +1703,8 @@ csio_enable_ports(struct csio_hw *hw)
return -EINVAL; return -EINVAL;
} }
csio_mb_process_read_port_rsp(hw, mbp, &retval, csio_mb_process_read_port_rsp(hw, mbp, &retval, fw_caps,
&hw->pport[i].pcap); &pcaps, &acaps);
if (retval != FW_SUCCESS) { if (retval != FW_SUCCESS) {
csio_err(hw, "FW_PORT_CMD(r) port:%d failed: 0x%x\n", csio_err(hw, "FW_PORT_CMD(r) port:%d failed: 0x%x\n",
portid, retval); portid, retval);
...@@ -1451,9 +1712,13 @@ csio_enable_ports(struct csio_hw *hw) ...@@ -1451,9 +1712,13 @@ csio_enable_ports(struct csio_hw *hw)
return -EINVAL; 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 */ /* Write back PORT information */
csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid, true, csio_mb_port(hw, mbp, CSIO_MB_DEFAULT_TMO, portid,
(PAUSE_RX | PAUSE_TX), hw->pport[i].pcap, NULL); true, rcaps, fw_caps, NULL);
if (csio_mb_issue(hw, mbp)) { if (csio_mb_issue(hw, mbp)) {
csio_err(hw, "failed to issue FW_PORT_CMD(w) port:%d\n", csio_err(hw, "failed to issue FW_PORT_CMD(w) port:%d\n",
......
...@@ -268,8 +268,62 @@ struct csio_vpd { ...@@ -268,8 +268,62 @@ struct csio_vpd {
uint8_t id[ID_LEN + 1]; 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 { struct csio_pport {
uint16_t pcap; uint16_t pcap;
uint16_t acap;
uint8_t portid; uint8_t portid;
uint8_t link_status; uint8_t link_status;
uint16_t link_speed; uint16_t link_speed;
...@@ -278,6 +332,7 @@ struct csio_pport { ...@@ -278,6 +332,7 @@ struct csio_pport {
uint8_t rsvd1; uint8_t rsvd1;
uint8_t rsvd2; uint8_t rsvd2;
uint8_t rsvd3; uint8_t rsvd3;
struct link_config link_cfg;
}; };
/* fcoe resource information */ /* fcoe resource information */
...@@ -582,6 +637,10 @@ int csio_hw_slow_intr_handler(struct csio_hw *); ...@@ -582,6 +637,10 @@ int csio_hw_slow_intr_handler(struct csio_hw *);
int csio_handle_intr_status(struct csio_hw *, unsigned int, int csio_handle_intr_status(struct csio_hw *, unsigned int,
const struct intr_info *); 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_start(struct csio_hw *);
int csio_hw_stop(struct csio_hw *); int csio_hw_stop(struct csio_hw *);
int csio_hw_reset(struct csio_hw *); int csio_hw_reset(struct csio_hw *);
......
...@@ -352,6 +352,14 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) ...@@ -352,6 +352,14 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
val = htonl(FC_PORTSPEED_1GBIT); val = htonl(FC_PORTSPEED_1GBIT);
else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_10G) else if (hw->pport[ln->portid].link_speed == FW_PORT_CAP_SPEED_10G)
val = htonl(FC_PORTSPEED_10GBIT); 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 else
val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN); val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN);
csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED, csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED,
......
...@@ -326,10 +326,6 @@ csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, ...@@ -326,10 +326,6 @@ csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_TARGET); 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 * csio_mb_port- FW PORT command helper
* @hw: The HW structure * @hw: The HW structure
...@@ -344,11 +340,10 @@ csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, ...@@ -344,11 +340,10 @@ csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
*/ */
void void
csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 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 *)) void (*cbfn) (struct csio_hw *, struct csio_mb *))
{ {
struct fw_port_cmd *cmdp = (struct fw_port_cmd *)(mbp->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); CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
...@@ -358,26 +353,24 @@ csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, ...@@ -358,26 +353,24 @@ csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
FW_PORT_CMD_PORTID_V(portid)); FW_PORT_CMD_PORTID_V(portid));
if (!wr) { if (!wr) {
cmdp->action_to_len16 = htonl( 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)); FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
return; return;
} }
/* Set port */ /* Set port */
cmdp->action_to_len16 = htonl( 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)); FW_CMD_LEN16_V(sizeof(*cmdp) / 16));
if (fc & PAUSE_RX) if (fw_caps == FW_CAPS16)
lfc |= FW_PORT_CAP_FC_RX; cmdp->u.l1cfg.rcap = cpu_to_be32(fc);
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);
else else
cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | cmdp->u.l1cfg32.rcap32 = cpu_to_be32(fc);
lfc | mdi);
} }
/* /*
...@@ -390,14 +383,22 @@ csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, ...@@ -390,14 +383,22 @@ csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
*/ */
void void
csio_mb_process_read_port_rsp(struct csio_hw *hw, struct csio_mb *mbp, 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); struct fw_port_cmd *rsp = (struct fw_port_cmd *)(mbp->mb);
*retval = FW_CMD_RETVAL_G(ntohl(rsp->action_to_len16)); *retval = FW_CMD_RETVAL_G(ntohl(rsp->action_to_len16));
if (*retval == FW_SUCCESS) if (*retval == FW_SUCCESS) {
*caps = ntohs(rsp->u.info.pcap); 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, __be64 *cmd) ...@@ -1409,6 +1410,7 @@ csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd)
uint32_t link_status; uint32_t link_status;
uint16_t action; uint16_t action;
uint8_t mod_type; uint8_t mod_type;
fw_port_cap32_t linkattr;
if (opcode == FW_PORT_CMD) { if (opcode == FW_PORT_CMD) {
pcmd = (struct fw_port_cmd *)cmd; pcmd = (struct fw_port_cmd *)cmd;
...@@ -1416,22 +1418,34 @@ csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd) ...@@ -1416,22 +1418,34 @@ csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd)
ntohl(pcmd->op_to_portid)); ntohl(pcmd->op_to_portid));
action = FW_PORT_CMD_ACTION_G( action = FW_PORT_CMD_ACTION_G(
ntohl(pcmd->action_to_len16)); 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", csio_err(hw, "Unhandled FW_PORT_CMD action: %u\n",
action); action);
return -EINVAL; return -EINVAL;
} }
if (action == FW_PORT_ACTION_GET_PORT_INFO) {
link_status = ntohl(pcmd->u.info.lstatus_to_modtype); link_status = ntohl(pcmd->u.info.lstatus_to_modtype);
mod_type = FW_PORT_CMD_MODTYPE_G(link_status); mod_type = FW_PORT_CMD_MODTYPE_G(link_status);
linkattr = lstatus_to_fwcap(link_status);
hw->pport[port_id].link_status = hw->pport[port_id].link_status =
FW_PORT_CMD_LSTATUS_G(link_status); FW_PORT_CMD_LSTATUS_G(link_status);
hw->pport[port_id].link_speed = } else {
FW_PORT_CMD_LSPEED_G(link_status); 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_speed = fwcap_to_fwspeed(linkattr);
csio_info(hw, "Port:%x - LINK %s\n", port_id, 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) { if (mod_type != hw->pport[port_id].mod_type) {
hw->pport[port_id].mod_type = mod_type; hw->pport[port_id].mod_type = mod_type;
......
...@@ -88,12 +88,6 @@ enum csio_dev_state { ...@@ -88,12 +88,6 @@ enum csio_dev_state {
FW_PARAMS_PARAM_Y_V(0) | \ FW_PARAMS_PARAM_Y_V(0) | \
FW_PARAMS_PARAM_Z_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) \ #define CSIO_INIT_MBP(__mbp, __cp, __tmo, __priv, __fn, __clear) \
do { \ do { \
if (__clear) \ if (__clear) \
...@@ -189,7 +183,8 @@ void csio_mb_port(struct csio_hw *, struct csio_mb *, uint32_t, ...@@ -189,7 +183,8 @@ void csio_mb_port(struct csio_hw *, struct csio_mb *, uint32_t,
void (*) (struct csio_hw *, struct csio_mb *)); void (*) (struct csio_hw *, struct csio_mb *));
void csio_mb_process_read_port_rsp(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 csio_mb_initialize(struct csio_hw *, struct csio_mb *, uint32_t,
void (*)(struct csio_hw *, struct csio_mb *)); void (*)(struct csio_hw *, struct csio_mb *));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment