mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-14 15:54:15 +08:00
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: Varun Prakash <varun@chelsio.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
1929e82e37
commit
e1735d9a98
@ -274,12 +274,24 @@ csio_get_host_speed(struct Scsi_Host *shost)
|
||||
|
||||
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;
|
||||
|
@ -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, ¶m, &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",
|
||||
|
@ -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 csio_hw *);
|
||||
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 *);
|
||||
|
@ -352,6 +352,14 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req)
|
||||
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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
#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, struct csio_mb *mbp, uint32_t tmo,
|
||||
*/
|
||||
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 csio_mb *mbp, uint32_t tmo,
|
||||
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 csio_mb *mbp, uint32_t tmo,
|
||||
*/
|
||||
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, __be64 *cmd)
|
||||
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, __be64 *cmd)
|
||||
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);
|
||||
hw->pport[port_id].link_speed =
|
||||
FW_PORT_CMD_LSPEED_G(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_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;
|
||||
|
@ -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) \
|
||||
@ -189,7 +183,8 @@ void csio_mb_port(struct csio_hw *, struct csio_mb *, uint32_t,
|
||||
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 *));
|
||||
|
Loading…
Reference in New Issue
Block a user