Commit 577f0d1b authored by Veerasenareddy Burru's avatar Veerasenareddy Burru Committed by David S. Miller

octeon_ep: add separate mailbox command and response queues

Enhance control mailbox protocol to support following
 - separate command and response queues
    * command queue to send control commands to firmware.
    * response queue to receive responses and notifications from
      firmware.
 - variable size messages using scatter/gather
Signed-off-by: default avatarAbhijit Ayarekar <aayarekar@marvell.com>
Signed-off-by: default avatarVeerasenareddy Burru <vburru@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7c05d3d0
......@@ -27,50 +27,39 @@
* |-------------------------------------------|
* |producer index (4 bytes) |
* |consumer index (4 bytes) |
* |element size (4 bytes) |
* |element count (4 bytes) |
* |max element size (4 bytes) |
* |reserved (4 bytes) |
* |===========================================|
* |Fw to Host Queue info (16 bytes) |
* |-------------------------------------------|
* |producer index (4 bytes) |
* |consumer index (4 bytes) |
* |element size (4 bytes) |
* |element count (4 bytes) |
* |max element size (4 bytes) |
* |reserved (4 bytes) |
* |===========================================|
* |Host to Fw Queue |
* |Host to Fw Queue ((total size-288/2) bytes)|
* |-------------------------------------------|
* |((elem_sz + hdr(8 bytes)) * elem_cnt) bytes|
* | |
* |===========================================|
* |===========================================|
* |Fw to Host Queue |
* |Fw to Host Queue ((total size-288/2) bytes)|
* |-------------------------------------------|
* |((elem_sz + hdr(8 bytes)) * elem_cnt) bytes|
* | |
* |===========================================|
*/
#define OCTEP_CTRL_MBOX_MAGIC_NUMBER 0xdeaddeadbeefbeefull
/* Size of mbox info in bytes */
#define OCTEP_CTRL_MBOX_INFO_SZ 256
/* Size of mbox host to target queue info in bytes */
#define OCTEP_CTRL_MBOX_H2FQ_INFO_SZ 16
/* Size of mbox target to host queue info in bytes */
#define OCTEP_CTRL_MBOX_F2HQ_INFO_SZ 16
/* Size of mbox queue in bytes */
#define OCTEP_CTRL_MBOX_Q_SZ(sz, cnt) (((sz) + 8) * (cnt))
/* Size of mbox in bytes */
#define OCTEP_CTRL_MBOX_SZ(hsz, hcnt, fsz, fcnt) (OCTEP_CTRL_MBOX_INFO_SZ + \
OCTEP_CTRL_MBOX_H2FQ_INFO_SZ + \
OCTEP_CTRL_MBOX_F2HQ_INFO_SZ + \
OCTEP_CTRL_MBOX_Q_SZ(hsz, hcnt) + \
OCTEP_CTRL_MBOX_Q_SZ(fsz, fcnt))
/* Valid request message */
#define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_REQ BIT(0)
/* Valid response message */
#define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_RESP BIT(1)
/* Valid notification, no response required */
#define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_NOTIFY BIT(2)
/* Valid custom message */
#define OCTEP_CTRL_MBOX_MSG_HDR_FLAG_CUSTOM BIT(3)
#define OCTEP_CTRL_MBOX_MSG_DESC_MAX 4
enum octep_ctrl_mbox_status {
OCTEP_CTRL_MBOX_STATUS_INVALID = 0,
......@@ -81,31 +70,48 @@ enum octep_ctrl_mbox_status {
/* mbox message */
union octep_ctrl_mbox_msg_hdr {
u64 word0;
u64 words[2];
struct {
/* must be 0 */
u16 reserved1:15;
/* vf_idx is valid if 1 */
u16 is_vf:1;
/* sender vf index 0-(n-1), 0 if (is_vf==0) */
u16 vf_idx;
/* total size of message excluding header */
u32 sz;
/* OCTEP_CTRL_MBOX_MSG_HDR_FLAG_* */
u32 flags;
/* size of message in words excluding header */
u32 sizew;
};
/* identifier to match responses */
u16 msg_id;
u16 reserved2;
} s;
};
/* mbox message buffer */
struct octep_ctrl_mbox_msg_buf {
u32 reserved1;
u16 reserved2;
/* size of buffer */
u16 sz;
/* pointer to message buffer */
void *msg;
};
/* mbox message */
struct octep_ctrl_mbox_msg {
/* mbox transaction header */
union octep_ctrl_mbox_msg_hdr hdr;
/* pointer to message buffer */
void *msg;
/* number of sg buffer's */
int sg_num;
/* message buffer's */
struct octep_ctrl_mbox_msg_buf sg_list[OCTEP_CTRL_MBOX_MSG_DESC_MAX];
};
/* Mbox queue */
struct octep_ctrl_mbox_q {
/* q element size, should be aligned to unsigned long */
u16 elem_sz;
/* q element count, should be power of 2 */
u16 elem_cnt;
/* q mask */
u16 mask;
/* size of queue buffer */
u32 sz;
/* producer address in bar mem */
u8 __iomem *hw_prod;
/* consumer address in bar mem */
......@@ -115,16 +121,10 @@ struct octep_ctrl_mbox_q {
};
struct octep_ctrl_mbox {
/* host driver version */
u64 version;
/* size of bar memory */
u32 barmem_sz;
/* pointer to BAR memory */
u8 __iomem *barmem;
/* user context for callback, can be null */
void *user_ctx;
/* callback handler for processing request, called from octep_ctrl_mbox_recv */
int (*process_req)(void *user_ctx, struct octep_ctrl_mbox_msg *msg);
/* host-to-fw queue */
struct octep_ctrl_mbox_q h2fq;
/* fw-to-host queue */
......@@ -146,6 +146,8 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox);
/* Send mbox message.
*
* @param mbox: non-null pointer to struct octep_ctrl_mbox.
* @param msg: non-null pointer to struct octep_ctrl_mbox_msg.
* Caller should fill msg.sz and msg.desc.sz for each message.
*
* return value: 0 on success, -errno on failure.
*/
......@@ -154,6 +156,8 @@ int octep_ctrl_mbox_send(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_ms
/* Retrieve mbox message.
*
* @param mbox: non-null pointer to struct octep_ctrl_mbox.
* @param msg: non-null pointer to struct octep_ctrl_mbox_msg.
* Caller should fill msg.sz and msg.desc.sz for each message.
*
* return value: 0 on success, -errno on failure.
*/
......@@ -161,7 +165,7 @@ int octep_ctrl_mbox_recv(struct octep_ctrl_mbox *mbox, struct octep_ctrl_mbox_ms
/* Uninitialize control mbox.
*
* @param ep: non-null pointer to struct octep_ctrl_mbox.
* @param mbox: non-null pointer to struct octep_ctrl_mbox.
*
* return value: 0 on success, -errno on failure.
*/
......
......@@ -45,15 +45,18 @@ enum octep_ctrl_net_f2h_cmd {
OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS,
};
struct octep_ctrl_net_req_hdr {
/* sender id */
u16 sender;
/* receiver id */
u16 receiver;
/* octep_ctrl_net_h2t_cmd */
u16 cmd;
/* reserved */
u16 rsvd0;
union octep_ctrl_net_req_hdr {
u64 words[1];
struct {
/* sender id */
u16 sender;
/* receiver id */
u16 receiver;
/* octep_ctrl_net_h2t_cmd */
u16 cmd;
/* reserved */
u16 rsvd0;
} s;
};
/* get/set mtu request */
......@@ -110,7 +113,7 @@ struct octep_ctrl_net_h2f_req_cmd_link_info {
/* Host to fw request data */
struct octep_ctrl_net_h2f_req {
struct octep_ctrl_net_req_hdr hdr;
union octep_ctrl_net_req_hdr hdr;
union {
struct octep_ctrl_net_h2f_req_cmd_mtu mtu;
struct octep_ctrl_net_h2f_req_cmd_mac mac;
......@@ -121,15 +124,18 @@ struct octep_ctrl_net_h2f_req {
};
} __packed;
struct octep_ctrl_net_resp_hdr {
/* sender id */
u16 sender;
/* receiver id */
u16 receiver;
/* octep_ctrl_net_h2t_cmd */
u16 cmd;
/* octep_ctrl_net_reply */
u16 reply;
union octep_ctrl_net_resp_hdr {
u64 words[1];
struct {
/* sender id */
u16 sender;
/* receiver id */
u16 receiver;
/* octep_ctrl_net_h2t_cmd */
u16 cmd;
/* octep_ctrl_net_reply */
u16 reply;
} s;
};
/* get mtu response */
......@@ -152,7 +158,7 @@ struct octep_ctrl_net_h2f_resp_cmd_state {
/* Host to fw response data */
struct octep_ctrl_net_h2f_resp {
struct octep_ctrl_net_resp_hdr hdr;
union octep_ctrl_net_resp_hdr hdr;
union {
struct octep_ctrl_net_h2f_resp_cmd_mtu mtu;
struct octep_ctrl_net_h2f_resp_cmd_mac mac;
......@@ -170,7 +176,7 @@ struct octep_ctrl_net_f2h_req_cmd_state {
/* Fw to host request data */
struct octep_ctrl_net_f2h_req {
struct octep_ctrl_net_req_hdr hdr;
union octep_ctrl_net_req_hdr hdr;
union {
struct octep_ctrl_net_f2h_req_cmd_state link;
};
......@@ -178,56 +184,34 @@ struct octep_ctrl_net_f2h_req {
/* Fw to host response data */
struct octep_ctrl_net_f2h_resp {
struct octep_ctrl_net_resp_hdr hdr;
union octep_ctrl_net_resp_hdr hdr;
};
/* Size of host to fw octep_ctrl_mbox queue element */
union octep_ctrl_net_h2f_data_sz {
/* Max data size to be transferred over mbox */
union octep_ctrl_net_max_data {
struct octep_ctrl_net_h2f_req h2f_req;
struct octep_ctrl_net_h2f_resp h2f_resp;
};
/* Size of fw to host octep_ctrl_mbox queue element */
union octep_ctrl_net_f2h_data_sz {
struct octep_ctrl_net_f2h_req f2h_req;
struct octep_ctrl_net_f2h_resp f2h_resp;
};
/* size of host to fw data in words */
#define OCTEP_CTRL_NET_H2F_DATA_SZW ((sizeof(union octep_ctrl_net_h2f_data_sz)) / \
(sizeof(unsigned long)))
/* size of fw to host data in words */
#define OCTEP_CTRL_NET_F2H_DATA_SZW ((sizeof(union octep_ctrl_net_f2h_data_sz)) / \
(sizeof(unsigned long)))
/* size in words of get/set mtu request */
#define OCTEP_CTRL_NET_H2F_MTU_REQ_SZW 2
/* size in words of get/set mac request */
#define OCTEP_CTRL_NET_H2F_MAC_REQ_SZW 2
/* size in words of get stats request */
#define OCTEP_CTRL_NET_H2F_GET_STATS_REQ_SZW 2
/* size in words of get/set state request */
#define OCTEP_CTRL_NET_H2F_STATE_REQ_SZW 2
/* size in words of get/set link info request */
#define OCTEP_CTRL_NET_H2F_LINK_INFO_REQ_SZW 4
/* size in words of get mtu response */
#define OCTEP_CTRL_NET_H2F_GET_MTU_RESP_SZW 2
/* size in words of set mtu response */
#define OCTEP_CTRL_NET_H2F_SET_MTU_RESP_SZW 1
/* size in words of get mac response */
#define OCTEP_CTRL_NET_H2F_GET_MAC_RESP_SZW 2
/* size in words of set mac response */
#define OCTEP_CTRL_NET_H2F_SET_MAC_RESP_SZW 1
/* size in words of get state request */
#define OCTEP_CTRL_NET_H2F_GET_STATE_RESP_SZW 2
/* size in words of set state request */
#define OCTEP_CTRL_NET_H2F_SET_STATE_RESP_SZW 1
/* size in words of get link info request */
#define OCTEP_CTRL_NET_H2F_GET_LINK_INFO_RESP_SZW 4
/* size in words of set link info request */
#define OCTEP_CTRL_NET_H2F_SET_LINK_INFO_RESP_SZW 1
struct octep_ctrl_net_wait_data {
struct list_head list;
int done;
struct octep_ctrl_mbox_msg msg;
union {
struct octep_ctrl_net_h2f_req req;
struct octep_ctrl_net_h2f_resp resp;
} data;
};
/** Initialize data for ctrl net.
*
* @param oct: non-null pointer to struct octep_device.
*
* return value: 0 on success, -errno on error.
*/
int octep_ctrl_net_init(struct octep_device *oct);
/** Get link status from firmware.
*
......@@ -235,21 +219,29 @@ union octep_ctrl_net_f2h_data_sz {
*
* return value: link status 0=down, 1=up.
*/
int octep_get_link_status(struct octep_device *oct);
int octep_ctrl_net_get_link_status(struct octep_device *oct);
/** Set link status in firmware.
*
* @param oct: non-null pointer to struct octep_device.
* @param up: boolean status.
* @param wait_for_response: poll for response.
*
* return value: 0 on success, -errno on failure
*/
void octep_set_link_status(struct octep_device *oct, bool up);
int octep_ctrl_net_set_link_status(struct octep_device *oct, bool up,
bool wait_for_response);
/** Set rx state in firmware.
*
* @param oct: non-null pointer to struct octep_device.
* @param up: boolean status.
* @param wait_for_response: poll for response.
*
* return value: 0 on success, -errno on failure.
*/
void octep_set_rx_state(struct octep_device *oct, bool up);
int octep_ctrl_net_set_rx_state(struct octep_device *oct, bool up,
bool wait_for_response);
/** Get mac address from firmware.
*
......@@ -258,21 +250,29 @@ void octep_set_rx_state(struct octep_device *oct, bool up);
*
* return value: 0 on success, -errno on failure.
*/
int octep_get_mac_addr(struct octep_device *oct, u8 *addr);
int octep_ctrl_net_get_mac_addr(struct octep_device *oct, u8 *addr);
/** Set mac address in firmware.
*
* @param oct: non-null pointer to struct octep_device.
* @param addr: non-null pointer to mac address.
* @param wait_for_response: poll for response.
*
* return value: 0 on success, -errno on failure.
*/
int octep_set_mac_addr(struct octep_device *oct, u8 *addr);
int octep_ctrl_net_set_mac_addr(struct octep_device *oct, u8 *addr,
bool wait_for_response);
/** Set mtu in firmware.
*
* @param oct: non-null pointer to struct octep_device.
* @param mtu: mtu.
* @param wait_for_response: poll for response.
*
* return value: 0 on success, -errno on failure.
*/
int octep_set_mtu(struct octep_device *oct, int mtu);
int octep_ctrl_net_set_mtu(struct octep_device *oct, int mtu,
bool wait_for_response);
/** Get interface statistics from firmware.
*
......@@ -280,7 +280,7 @@ int octep_set_mtu(struct octep_device *oct, int mtu);
*
* return value: 0 on success, -errno on failure.
*/
int octep_get_if_stats(struct octep_device *oct);
int octep_ctrl_net_get_if_stats(struct octep_device *oct);
/** Get link info from firmware.
*
......@@ -288,12 +288,32 @@ int octep_get_if_stats(struct octep_device *oct);
*
* return value: 0 on success, -errno on failure.
*/
int octep_get_link_info(struct octep_device *oct);
int octep_ctrl_net_get_link_info(struct octep_device *oct);
/** Set link info in firmware.
*
* @param oct: non-null pointer to struct octep_device.
* @param link_info: non-null pointer to struct octep_iface_link_info.
* @param wait_for_response: poll for response.
*
* return value: 0 on success, -errno on failure.
*/
int octep_ctrl_net_set_link_info(struct octep_device *oct,
struct octep_iface_link_info *link_info,
bool wait_for_response);
/** Poll for firmware messages and process them.
*
* @param oct: non-null pointer to struct octep_device.
*/
void octep_ctrl_net_recv_fw_messages(struct octep_device *oct);
/** Uninitialize data for ctrl net.
*
* @param oct: non-null pointer to struct octep_device.
*
* return value: 0 on success, -errno on error.
*/
int octep_set_link_info(struct octep_device *oct, struct octep_iface_link_info *link_info);
int octep_ctrl_net_uninit(struct octep_device *oct);
#endif /* __OCTEP_CTRL_NET_H__ */
......@@ -150,7 +150,7 @@ octep_get_ethtool_stats(struct net_device *netdev,
rx_packets = 0;
rx_bytes = 0;
octep_get_if_stats(oct);
octep_ctrl_net_get_if_stats(oct);
iface_tx_stats = &oct->iface_tx_stats;
iface_rx_stats = &oct->iface_rx_stats;
......@@ -283,7 +283,7 @@ static int octep_get_link_ksettings(struct net_device *netdev,
ethtool_link_ksettings_zero_link_mode(cmd, supported);
ethtool_link_ksettings_zero_link_mode(cmd, advertising);
octep_get_link_info(oct);
octep_ctrl_net_get_link_info(oct);
advertised_modes = oct->link_info.advertised_modes;
supported_modes = oct->link_info.supported_modes;
......@@ -439,7 +439,7 @@ static int octep_set_link_ksettings(struct net_device *netdev,
link_info_new.speed = cmd->base.speed;
link_info_new.autoneg = autoneg;
err = octep_set_link_info(oct, &link_info_new);
err = octep_ctrl_net_set_link_info(oct, &link_info_new, true);
if (err)
return err;
......
......@@ -507,11 +507,8 @@ static int octep_open(struct net_device *netdev)
octep_napi_enable(oct);
oct->link_info.admin_up = 1;
octep_set_rx_state(oct, true);
ret = octep_get_link_status(oct);
if (!ret)
octep_set_link_status(oct, true);
octep_ctrl_net_set_rx_state(oct, true, false);
octep_ctrl_net_set_link_status(oct, true, false);
oct->poll_non_ioq_intr = false;
/* Enable the input and output queues for this Octeon device */
......@@ -522,7 +519,7 @@ static int octep_open(struct net_device *netdev)
octep_oq_dbell_init(oct);
ret = octep_get_link_status(oct);
ret = octep_ctrl_net_get_link_status(oct);
if (ret > 0)
octep_link_up(netdev);
......@@ -552,14 +549,14 @@ static int octep_stop(struct net_device *netdev)
netdev_info(netdev, "Stopping the device ...\n");
octep_ctrl_net_set_link_status(oct, false, false);
octep_ctrl_net_set_rx_state(oct, false, false);
/* Stop Tx from stack */
netif_tx_stop_all_queues(netdev);
netif_carrier_off(netdev);
netif_tx_disable(netdev);
octep_set_link_status(oct, false);
octep_set_rx_state(oct, false);
oct->link_info.admin_up = 0;
oct->link_info.oper_up = 0;
......@@ -761,7 +758,9 @@ static void octep_get_stats64(struct net_device *netdev,
struct octep_device *oct = netdev_priv(netdev);
int q;
octep_get_if_stats(oct);
if (netif_running(netdev))
octep_ctrl_net_get_if_stats(oct);
tx_packets = 0;
tx_bytes = 0;
rx_packets = 0;
......@@ -832,7 +831,7 @@ static int octep_set_mac(struct net_device *netdev, void *p)
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
err = octep_set_mac_addr(oct, addr->sa_data);
err = octep_ctrl_net_set_mac_addr(oct, addr->sa_data, true);
if (err)
return err;
......@@ -852,7 +851,7 @@ static int octep_change_mtu(struct net_device *netdev, int new_mtu)
if (link_info->mtu == new_mtu)
return 0;
err = octep_set_mtu(oct, new_mtu);
err = octep_ctrl_net_set_mtu(oct, new_mtu, true);
if (!err) {
oct->link_info.mtu = new_mtu;
netdev->mtu = new_mtu;
......@@ -904,34 +903,8 @@ static void octep_ctrl_mbox_task(struct work_struct *work)
{
struct octep_device *oct = container_of(work, struct octep_device,
ctrl_mbox_task);
struct net_device *netdev = oct->netdev;
struct octep_ctrl_net_f2h_req req = {};
struct octep_ctrl_mbox_msg msg;
int ret = 0;
msg.msg = &req;
while (true) {
ret = octep_ctrl_mbox_recv(&oct->ctrl_mbox, &msg);
if (ret)
break;
switch (req.hdr.cmd) {
case OCTEP_CTRL_NET_F2H_CMD_LINK_STATUS:
if (netif_running(netdev)) {
if (req.link.state) {
dev_info(&oct->pdev->dev, "netif_carrier_on\n");
netif_carrier_on(netdev);
} else {
dev_info(&oct->pdev->dev, "netif_carrier_off\n");
netif_carrier_off(netdev);
}
}
break;
default:
pr_info("Unknown mbox req : %u\n", req.hdr.cmd);
break;
}
}
octep_ctrl_net_recv_fw_messages(oct);
}
static const char *octep_devid_to_str(struct octep_device *oct)
......@@ -955,9 +928,8 @@ static const char *octep_devid_to_str(struct octep_device *oct)
*/
int octep_device_setup(struct octep_device *oct)
{
struct octep_ctrl_mbox *ctrl_mbox;
struct pci_dev *pdev = oct->pdev;
int i, ret;
int i;
/* allocate memory for oct->conf */
oct->conf = kzalloc(sizeof(*oct->conf), GFP_KERNEL);
......@@ -992,20 +964,7 @@ int octep_device_setup(struct octep_device *oct)
oct->pkind = CFG_GET_IQ_PKIND(oct->conf);
/* Initialize control mbox */
ctrl_mbox = &oct->ctrl_mbox;
ctrl_mbox->barmem = CFG_GET_CTRL_MBOX_MEM_ADDR(oct->conf);
ret = octep_ctrl_mbox_init(ctrl_mbox);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize control mbox\n");
goto unsupported_dev;
}
oct->ctrl_mbox_ifstats_offset = OCTEP_CTRL_MBOX_SZ(ctrl_mbox->h2fq.elem_sz,
ctrl_mbox->h2fq.elem_cnt,
ctrl_mbox->f2hq.elem_sz,
ctrl_mbox->f2hq.elem_cnt);
return 0;
return octep_ctrl_net_init(oct);
unsupported_dev:
for (i = 0; i < OCTEP_MMIO_REGIONS; i++)
......@@ -1033,7 +992,7 @@ static void octep_device_cleanup(struct octep_device *oct)
oct->mbox[i] = NULL;
}
octep_ctrl_mbox_uninit(&oct->ctrl_mbox);
octep_ctrl_net_uninit(oct);
oct->hw_ops.soft_reset(oct);
for (i = 0; i < OCTEP_MMIO_REGIONS; i++) {
......@@ -1143,7 +1102,8 @@ static int octep_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->max_mtu = OCTEP_MAX_MTU;
netdev->mtu = OCTEP_DEFAULT_MTU;
err = octep_get_mac_addr(octep_dev, octep_dev->mac_addr);
err = octep_ctrl_net_get_mac_addr(octep_dev,
octep_dev->mac_addr);
if (err) {
dev_err(&pdev->dev, "Failed to get mac address\n");
goto register_dev_err;
......
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